Merge branch 'master' into 7-assign-team-to-repo

This commit is contained in:
M M Arif 2020-10-12 18:04:27 +05:00
commit f727ec51b8
36 changed files with 1475 additions and 2090 deletions

View File

@ -72,13 +72,11 @@ Thanks to all the open source libraries, contributors and donators.
- Retrofit
- Gson
- Okhttp
- ViHtarb/tooltip
- Picasso
- Markwon
- Prettytime
- Amulyakhare/textdrawable
- Vdurmont/emoji-java
- Abumoallim/android-multi-select-dialog
- Pes/materialcolorpicker
- Hendraanggrian/socialview
- HamidrezaAmz/BreadcrumbsView

View File

@ -66,7 +66,6 @@ dependencies {
testImplementation "junit:junit:4.13"
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation "com.github.vihtarb:tooltip:0.2.0"
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation "com.google.code.gson:gson:2.8.6"
implementation "com.squareup.picasso:picasso:2.71828"

View File

@ -17,49 +17,79 @@
android:supportsRtl="true"
tools:targetApi="n">
<activity android:name=".activities.MergePullRequestActivity" />
<activity
android:name=".activities.MergePullRequestActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.FileViewActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.CreateFileActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.RepoWatchersActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".activities.RepoStargazersActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.AdminGetUsersActivity" />
<activity
android:name=".activities.AddRemoveAssigneesActivity"
android:theme="@style/Theme.AppCompat.Light.Dialog" />
<activity android:name=".activities.CreateReleaseActivity" />
<activity android:name=".activities.EditIssueActivity" />
<activity android:name=".activities.CreateNewUserActivity" />
android:name=".activities.AdminGetUsersActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddRemoveLabelsActivity"
android:theme="@style/Theme.AppCompat.Light.Dialog" />
<activity android:name=".activities.ProfileEmailActivity" />
<activity android:name=".activities.AddCollaboratorToRepositoryActivity" />
<activity android:name=".activities.CreateTeamByOrgActivity" />
<activity android:name=".activities.OrganizationTeamMembersActivity" />
android:name=".activities.CreateReleaseActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.EditIssueActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateNewUserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.ProfileEmailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddCollaboratorToRepositoryActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateTeamByOrgActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.OrganizationTeamMembersActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.OrganizationDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:label="@string/title_activity_org_detail"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.CreateLabelActivity" />
<activity android:name=".activities.CreateIssueActivity" />
<activity android:name=".activities.CreateMilestoneActivity" />
<activity android:name=".activities.ReplyToIssueActivity" />
<activity
android:name=".activities.CreateLabelActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateIssueActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateMilestoneActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.ReplyToIssueActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.IssueDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:windowSoftInputMode="adjustNothing" />
<activity
android:name=".activities.RepoDetailActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:label="@string/title_activity_repo_detail"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".activities.MainActivity" android:theme="@android:style/Theme.NoTitleBar" android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation">
<activity
android:name=".activities.MainActivity"
android:theme="@android:style/Theme.NoTitleBar"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -68,24 +98,61 @@
</activity>
<activity
android:name=".activities.LoginActivity"
android:launchMode="singleTask" android:theme="@android:style/Theme.NoTitleBar"/>
<activity android:name=".activities.CreateRepoActivity" />
<activity android:name=".activities.CreateOrganizationActivity" />
<activity android:name=".activities.OpenRepoInBrowserActivity" />
<activity android:name=".activities.FileDiffActivity" />
<activity android:name=".activities.CommitsActivity" />
<activity android:name=".helpers.ssl.MemorizingActivity" android:theme="@android:style/Theme.Material.Dialog" />
<activity android:name=".activities.SettingsAppearanceActivity" />
<activity android:name=".activities.SettingsFileViewerActivity" />
<activity android:name=".activities.SettingsSecurityActivity" />
<activity android:name=".activities.SettingsTranslationActivity" />
<activity android:name=".activities.SettingsReportsActivity" />
<activity android:name=".activities.AddNewTeamMemberActivity" />
<activity android:name=".activities.SettingsDraftsActivity" />
<activity android:name=".activities.RepoForksActivity" />
<activity android:name=".activities.AddNewAccountActivity" />
<activity android:name=".activities.RepositorySettingsActivity" />
<activity android:name=".activities.CreatePullRequestActivity" />
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:launchMode="singleTask"
android:theme="@android:style/Theme.NoTitleBar"/>
<activity
android:name=".activities.CreateRepoActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreateOrganizationActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.OpenRepoInBrowserActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.FileDiffActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CommitsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".helpers.ssl.MemorizingActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:theme="@android:style/Theme.Material.Dialog" />
<activity
android:name=".activities.SettingsAppearanceActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsFileViewerActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsSecurityActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsTranslationActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsReportsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddNewTeamMemberActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsDraftsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.RepoForksActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AddNewAccountActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.RepositorySettingsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.CreatePullRequestActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>

View File

@ -0,0 +1,122 @@
package org.mian.gitnex.actions;
import android.app.Dialog;
import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class AssigneesActions {
public static void getCurrentIssueAssignees(Context ctx, String instanceUrl, String loginUid, String instanceToken, String repoOwner, String repoName, int issueIndex, List<String> currentAssignees) {
Call<Issues> callSingleIssueLabels = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex);
callSingleIssueLabels.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++) {
currentAssignees.add(issueAssigneesList.getAssignees().get(i).getLogin());
}
}
}
}
}
@Override
public void onFailure(@NonNull Call<Issues> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static void getRepositoryAssignees(Context ctx, String instanceUrl, String instanceToken, String repoOwner, String repoName, List<Collaborators> assigneesList, Dialog dialogAssignees, AssigneesListAdapter assigneesAdapter, CustomAssigneesSelectionDialogBinding assigneesBinding) {
TinyDB tinyDB = new TinyDB(ctx);
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(instanceToken, repoOwner, repoName);
call.enqueue(new Callback<List<Collaborators>>() {
@Override
public void onResponse(@NonNull Call<List<Collaborators>> call, @NonNull retrofit2.Response<List<Collaborators>> response) {
assigneesList.clear();
List<Collaborators> assigneesList_ = response.body();
assigneesBinding.progressBar.setVisibility(View.GONE);
assigneesBinding.dialogFrame.setVisibility(View.VISIBLE);
if (response.code() == 200) {
assert assigneesList_ != null;
if(assigneesList_.size() > 0) {
dialogAssignees.show();
assigneesList.add(new Collaborators(tinyDB.getString("userFullname"), tinyDB.getString("loginUid"), tinyDB.getString("userAvatar")));
assigneesList.addAll(assigneesList_);
}
else {
dialogAssignees.dismiss();
Toasty.warning(ctx, ctx.getResources().getString(R.string.noAssigneesFound));
}
assigneesBinding.assigneesRecyclerView.setAdapter(assigneesAdapter);
}
else {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<List<Collaborators>> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
}

View File

@ -0,0 +1,116 @@
package org.mian.gitnex.actions;
import android.app.Dialog;
import android.content.Context;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Labels;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class LabelsActions {
public static void getCurrentIssueLabels(Context ctx, String instanceUrl, String loginUid, String instanceToken, String repoOwner, String repoName, int issueIndex, List<Integer> currentLabelsIds) {
Call<List<Labels>> callSingleIssueLabels = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getIssueLabels(Authorization.returnAuthentication(ctx, 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++) {
currentLabelsIds.add(issueLabelsList.get(i).getId());
}
}
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
public static void getRepositoryLabels(Context ctx, String instanceUrl, String instanceToken, String repoOwner, String repoName, List<Labels> labelsList, Dialog dialogLabels, LabelsListAdapter labelsAdapter, CustomLabelsSelectionDialogBinding labelsBinding) {
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getlabels(instanceToken, repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
labelsList.clear();
List<Labels> labelsList_ = response.body();
labelsBinding.progressBar.setVisibility(View.GONE);
labelsBinding.dialogFrame.setVisibility(View.VISIBLE);
if (response.code() == 200) {
assert labelsList_ != null;
if(labelsList_.size() > 0) {
dialogLabels.show();
labelsList.addAll(labelsList_);
}
else {
dialogLabels.dismiss();
Toasty.warning(ctx, ctx.getResources().getString(R.string.noLabelsFound));
}
labelsBinding.labelsRecyclerView.setAdapter(labelsAdapter);
}
else {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getResources().getString(R.string.genericServerResponseError));
}
});
}
}

View File

@ -1,294 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
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.TinyDB;
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.UpdateIssueAssignees;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class AddRemoveAssigneesActivity extends BaseActivity {
private ArrayList<MultiSelectModel> listOfCollaborators = new ArrayList<>();
private ArrayList<Integer> issueAssigneesIds = new ArrayList<>();
private Boolean assigneesFlag = false;
private MultiSelectDialog multiSelectDialogAssignees;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_add_remove_assignees;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
//supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
TinyDB tinyDb = new TinyDB(appCtx);
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(appCtx);
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, 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, ctx)
.getApiInterface()
.getIssueByIndex(Authorization.returnAuthentication(ctx, 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(List<Integer> selectedIds, List<String> selectedNames, String dataString) {
Log.i("selectedNames", String.valueOf(selectedNames));
updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(ctx, 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(List<Integer> selectedIds, List<String> selectedNames, String dataString) {
updateIssueAssignees(instanceUrl, Authorization.returnAuthentication(ctx, 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.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.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) {
UpdateIssueAssignees updateAssigneeJson = new UpdateIssueAssignees(issueAssigneesList);
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.patchIssueAssignees(Authorization.returnAuthentication(ctx, 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.success(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.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response2.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
}

View File

@ -1,308 +0,0 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
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.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.MultiSelectModel;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class AddRemoveLabelsActivity extends BaseActivity {
private ArrayList<MultiSelectModel> listOfLabels = new ArrayList<>();
private ArrayList<Integer> issueLabelIds = new ArrayList<>();
private Boolean labelsFlag = false;
private MultiSelectDialog multiSelectDialogLabels;
final Context ctx = this;
private Context appCtx;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_add_remove_labels;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
//supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().getDecorView().setBackground(new ColorDrawable(Color.TRANSPARENT));
TinyDB tinyDb = new TinyDB(appCtx);
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(appCtx);
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getlabels(Authorization.returnAuthentication(ctx, 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, ctx)
.getApiInterface()
.getIssueLabels(Authorization.returnAuthentication(ctx, 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(List<Integer> selectedIds, List<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(ctx, 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(List<Integer> selectedIds, List<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(ctx, 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.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.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, ctx)
.getApiInterface()
.updateIssueLabels(Authorization.returnAuthentication(ctx, 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.success(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.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void CloseActivity() {
this.finish();
}
}

View File

@ -24,6 +24,7 @@ import org.mian.gitnex.clients.AppApiService;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.interfaces.ApiInterface;
import org.mian.gitnex.models.Commits;
@ -115,7 +116,6 @@ public class CommitsActivity extends BaseActivity {
int page = (commitsList.size() + resultLimit) / resultLimit;
loadMore(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, page, branchName, resultLimit);
}
}));
@ -138,7 +138,7 @@ public class CommitsActivity extends BaseActivity {
@Override
public void onResponse(@NonNull Call<List<Commits>> call, @NonNull Response<List<Commits>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
assert response.body() != null;
if(response.body().size() > 0) {
@ -150,13 +150,15 @@ public class CommitsActivity extends BaseActivity {
}
else {
commitsList.clear();
adapter.notifyDataChanged();
noData.setVisibility(View.VISIBLE);
}
}
if(response.code() == 409) {
progressBar.setVisibility(View.GONE);
noData.setVisibility(View.VISIBLE);
}
else {
@ -164,12 +166,13 @@ public class CommitsActivity extends BaseActivity {
}
progressBar.setVisibility(View.GONE);
}
@Override
public void onFailure(@NonNull Call<List<Commits>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
Toasty.error(ctx, getResources().getString(R.string.errorOnLogin));
}
});
@ -190,23 +193,19 @@ public class CommitsActivity extends BaseActivity {
if(response.isSuccessful()) {
List<Commits> result = response.body();
assert result != null;
if(result.size() > 0) {
pageSize = result.size();
commitsList.addAll(result);
}
else {
adapter.setMoreDataAvailable(false);
}
adapter.notifyDataChanged();
progressLoadMore.setVisibility(View.GONE);
}
else {
@ -214,13 +213,13 @@ public class CommitsActivity extends BaseActivity {
}
progressLoadMore.setVisibility(View.GONE);
}
@Override
public void onFailure(@NonNull Call<List<Commits>> call, @NonNull Throwable t) {
Log.e(TAG, t.toString());
Toasty.error(ctx, getResources().getString(R.string.errorOnLogin));
}
});

View File

@ -1,29 +1,29 @@
package org.mian.gitnex.activities;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
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 androidx.annotation.NonNull;
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.actions.AssigneesActions;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreateIssueBinding;
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.helpers.StaticGlobalVariables;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
@ -32,45 +32,50 @@ 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Author M M Arif
*/
public class CreateIssueActivity extends BaseActivity implements View.OnClickListener {
public class CreateIssueActivity extends BaseActivity implements View.OnClickListener, LabelsListAdapter.LabelsListAdapterListener, AssigneesListAdapter.AssigneesListAdapterListener {
private ActivityCreateIssueBinding viewBinding;
private CustomLabelsSelectionDialogBinding labelsBinding;
private CustomAssigneesSelectionDialogBinding assigneesBinding;
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;
private Context appCtx;
private TinyDB tinyDb;
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private Dialog dialogLabels;
private Dialog dialogAssignees;
private String labelsSetter;
private String assigneesSetter;
private int milestoneId;
List<Milestones> milestonesList = new ArrayList<>();
ArrayList<MultiSelectModel> listOfAssignees = new ArrayList<>();
ArrayList<MultiSelectModel> listOfLabels= new ArrayList<>();
private ArrayAdapter<Mention> defaultMentionAdapter;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
private LabelsListAdapter labelsAdapter;
private AssigneesListAdapter assigneesAdapter;
private List<Integer> labelsIds = new ArrayList<>();
private List<Labels> labelsList = new ArrayList<>();
private List<Milestones> milestonesList = new ArrayList<>();
private List<Collaborators> assigneesList = new ArrayList<>();
private List<String> assigneesListData = new ArrayList<>();
@Override
protected int getLayoutResourceId(){
protected int getLayoutResourceId() {
return R.layout.activity_create_issue;
}
@ -79,20 +84,24 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityCreateIssueBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TinyDB tinyDb = new TinyDB(appCtx);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
final String loginFullName = tinyDb.getString("userFullname");
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");
repoOwner = parts[0];
repoName = parts[1];
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
// require gitea 1.12 or higher
if(new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.0")) {
@ -100,71 +109,113 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
}
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);
newIssueTitle.requestFocus();
viewBinding.newIssueTitle.requestFocus();
assert imm != null;
imm.showSoftInput(newIssueTitle, InputMethodManager.SHOW_IMPLICIT);
imm.showSoftInput(viewBinding.newIssueTitle, InputMethodManager.SHOW_IMPLICIT);
defaultMentionAdapter = new MentionArrayAdapter<>(this);
loadCollaboratorsList();
newIssueDescription.setMentionAdapter(defaultMentionAdapter);
labelsAdapter = new LabelsListAdapter(labelsList, CreateIssueActivity.this, labelsIds);
assigneesAdapter = new AssigneesListAdapter(ctx, assigneesList, CreateIssueActivity.this, assigneesListData);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
viewBinding.close.setOnClickListener(onClickListener);
assigneesList.setOnClickListener(this);
newIssueLabels.setOnClickListener(this);
newIssueDueDate.setOnClickListener(this);
viewBinding.newIssueAssigneesList.setOnClickListener(this);
viewBinding.newIssueLabels.setOnClickListener(this);
viewBinding.newIssueDueDate.setOnClickListener(this);
newIssueMilestoneSpinner = findViewById(R.id.newIssueMilestoneSpinner);
getMilestones(instanceUrl, instanceToken, repoOwner, repoName, loginUid, resultLimit);
getLabels(instanceUrl, instanceToken, repoOwner, repoName, loginUid);
getCollaborators(instanceUrl, instanceToken, repoOwner, repoName, loginUid, loginFullName);
disableProcessButton();
viewBinding.newIssueLabels.setOnClickListener(newIssueLabels ->
showLabels()
);
viewBinding.newIssueAssigneesList.setOnClickListener(newIssueAssigneesList ->
showAssignees()
);
if(!connToInternet) {
createNewIssueButton.setEnabled(false);
viewBinding.createNewIssueButton.setEnabled(false);
}
else {
createNewIssueButton.setOnClickListener(this);
viewBinding.createNewIssueButton.setOnClickListener(this);
}
}
@Override
public void assigneesInterface(List<String> data) {
assigneesSetter = String.valueOf(data);
viewBinding.newIssueAssigneesList.setText(assigneesSetter.replace("]", "").replace("[", ""));
assigneesListData = data;
}
@Override
public void labelsInterface(List<String> data) {
labelsSetter = String.valueOf(data);
viewBinding.newIssueLabels.setText(labelsSetter.replace("]", "").replace("[", ""));
}
@Override
public void labelsIdsInterface(List<Integer> data) {
labelsIds = data;
}
private void showAssignees() {
dialogAssignees = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogAssignees.getWindow() != null) {
dialogAssignees.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
assigneesBinding = CustomAssigneesSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
View view = assigneesBinding.getRoot();
dialogAssignees.setContentView(view);
assigneesBinding.cancel.setOnClickListener(assigneesBinding_ ->
dialogAssignees.dismiss()
);
AssigneesActions.getRepositoryAssignees(ctx, instanceUrl, instanceToken, repoOwner, repoName, assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
}
private void showLabels() {
dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogLabels.getWindow() != null) {
dialogLabels.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
labelsBinding = CustomLabelsSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
View view = labelsBinding.getRoot();
dialogLabels.setContentView(view);
labelsBinding.cancel.setOnClickListener(labelsBinding_ ->
dialogLabels.dismiss()
);
LabelsActions.getRepositoryLabels(ctx, instanceUrl, instanceToken, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
}
private void processNewIssue() {
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
TinyDB tinyDb = new TinyDB(appCtx);
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();
String newIssueTitleForm = Objects.requireNonNull(viewBinding.newIssueTitle.getText()).toString();
String newIssueDescriptionForm = Objects.requireNonNull(viewBinding.newIssueDescription.getText()).toString();
String newIssueDueDateForm = Objects.requireNonNull(viewBinding.newIssueDueDate.getText()).toString();
if(!connToInternet) {
@ -177,101 +228,25 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
Toasty.error(ctx, getString(R.string.issueTitleEmpty));
return;
}
/*if (newIssueDescriptionForm.equals("")) {
Toasty.error(ctx, getString(R.string.issueDescriptionEmpty));
return;
}*/
if (newIssueDueDateForm.equals("")) {
newIssueDueDateForm = null;
} else {
}
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("") && !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);
createNewIssueFunc(instanceUrl, instanceToken, repoOwner, repoName, loginUid, newIssueDescriptionForm, newIssueDueDateForm, milestoneId, newIssueTitleForm);
}
public void loadCollaboratorsList() {
private void createNewIssueFunc(final String instanceUrl, final String instanceToken, String repoOwner, String repoName, String loginUid, String newIssueDescriptionForm, String newIssueDueDateForm, int newIssueMilestoneIdForm, String newIssueTitleForm) {
final TinyDB tinyDb = new TinyDB(appCtx);
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, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, 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.toString());
}
});
}
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);
CreateIssue createNewIssueJson = new CreateIssue(loginUid, newIssueDescriptionForm, false, newIssueDueDateForm, newIssueMilestoneIdForm, newIssueTitleForm, assigneesListData, labelsIds);
Call<JsonElement> call3;
@ -285,19 +260,14 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response2) {
if(response2.isSuccessful()) {
if(response2.code() == 201) {
if(response2.code() == 201) {
//Log.i("isSuccessful1", String.valueOf(response2.body()));
TinyDB tinyDb = new TinyDB(appCtx);
tinyDb.putBoolean("resumeIssues", true);
Toasty.success(ctx, getString(R.string.issueCreated));
enableProcessButton();
finish();
}
TinyDB tinyDb = new TinyDB(appCtx);
tinyDb.putBoolean("resumeIssues", true);
Toasty.success(ctx, getString(R.string.issueCreated));
enableProcessButton();
finish();
}
else if(response2.code() == 401) {
@ -306,21 +276,19 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else {
Toasty.error(ctx, 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());
Toasty.error(ctx, getString(R.string.genericServerResponseError));
enableProcessButton();
}
});
@ -368,12 +336,16 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
}
ArrayAdapter<Milestones> adapter = new ArrayAdapter<>(CreateIssueActivity.this,
R.layout.spinner_item, milestonesList);
R.layout.list_spinner_items, milestonesList);
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
newIssueMilestoneSpinner.setAdapter(adapter);
viewBinding.newIssueMilestoneSpinner.setAdapter(adapter);
enableProcessButton();
viewBinding.newIssueMilestoneSpinner.setOnItemClickListener ((parent, view, position, id) ->
milestoneId = milestonesList.get(position).getId()
);
}
}
@ -381,143 +353,8 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
@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, String loginFullName) {
Call<List<Collaborators>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getCollaborators(Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName);
listOfAssignees.add(new MultiSelectModel(-1, loginFullName));
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(List<Integer> selectedIds, List<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, ctx)
.getApiInterface()
.getlabels(Authorization.returnAuthentication(ctx, 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(List<Integer> selectedIds, List<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());
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
@ -525,23 +362,8 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
@Override
public void onClick(View v) {
if (v == assigneesList) {
if(assigneesFlag) {
multiSelectDialog.show(getSupportFragmentManager(), "multiSelectDialog");
}
else {
Toasty.warning(ctx, getResources().getString(R.string.noAssigneesFound));
}
}
else if (v == newIssueLabels) {
if(labelsFlag) {
multiSelectDialogLabels.show(getSupportFragmentManager(), "multiSelectDialogLabels");
}
else {
Toasty.warning(ctx, getResources().getString(R.string.noLabelsFound));
}
}
else if (v == newIssueDueDate) {
if (v == viewBinding.newIssueDueDate) {
final Calendar c = Calendar.getInstance();
int mYear = c.get(Calendar.YEAR);
@ -549,19 +371,10 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
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);
(view, year, monthOfYear, dayOfMonth) -> viewBinding.newIssueDueDate.setText(getString(R.string.setDueDate, year, (monthOfYear + 1), dayOfMonth)), mYear, mMonth, mDay);
datePickerDialog.show();
}
else if(v == createNewIssueButton) {
else if(v == viewBinding.createNewIssueButton) {
processNewIssue();
}
@ -569,11 +382,11 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
private void disableProcessButton() {
createNewIssueButton.setEnabled(false);
viewBinding.createNewIssueButton.setEnabled(false);
}
private void enableProcessButton() {
createNewIssueButton.setEnabled(true);
viewBinding.createNewIssueButton.setEnabled(true);
}
}

View File

@ -12,6 +12,7 @@ import android.widget.ArrayAdapter;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityCreatePrBinding;
@ -48,8 +49,8 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
private int resultLimit = StaticGlobalVariables.resultLimitOldGiteaInstances;
private Dialog dialogLabels;
private String labelsSetter;
private ArrayList<Integer> labelsIds = new ArrayList<>();
private ArrayList<String> assignees = new ArrayList<>();
private List<Integer> labelsIds = new ArrayList<>();
private List<String> assignees = new ArrayList<>();
private int milestoneId;
private String instanceUrl;
@ -96,7 +97,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
resultLimit = StaticGlobalVariables.resultLimitNewGiteaInstances;
}
labelsAdapter = new LabelsListAdapter(labelsList, CreatePullRequestActivity.this);
labelsAdapter = new LabelsListAdapter(labelsList, CreatePullRequestActivity.this, labelsIds);
ImageView closeActivity = findViewById(R.id.close);
@ -164,7 +165,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
//Log.e("processPullRequest", String.valueOf(milestoneId));
}
private void createPullRequest(String prTitle, String prDescription, String mergeInto, String pullFrom, int milestoneId, String dueDate, ArrayList<String> assignees) {
private void createPullRequest(String prTitle, String prDescription, String mergeInto, String pullFrom, int milestoneId, String dueDate, List<String> assignees) {
CreatePullRequest createPullRequest = new CreatePullRequest(prTitle, prDescription, loginUid, mergeInto, pullFrom, milestoneId, dueDate, assignees, labelsIds);
@ -213,14 +214,14 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
}
@Override
public void labelsStringData(ArrayList<String> data) {
public void labelsInterface(List<String> data) {
labelsSetter = String.valueOf(data);
viewBinding.prLabels.setText(labelsSetter.replace("]", "").replace("[", ""));
}
@Override
public void labelsIdsData(ArrayList<Integer> data) {
public void labelsIdsInterface(List<Integer> data) {
labelsIds = data;
}
@ -242,57 +243,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
dialogLabels.dismiss()
);
Call<List<Labels>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getlabels(instanceToken, repoOwner, repoName);
call.enqueue(new Callback<List<Labels>>() {
@Override
public void onResponse(@NonNull Call<List<Labels>> call, @NonNull retrofit2.Response<List<Labels>> response) {
labelsList.clear();
List<Labels> labelsList_ = response.body();
labelsBinding.progressBar.setVisibility(View.GONE);
labelsBinding.dialogFrame.setVisibility(View.VISIBLE);
if (response.code() == 200) {
assert labelsList_ != null;
if(labelsList_.size() > 0) {
for (int i = 0; i < labelsList_.size(); i++) {
labelsList.add(new Labels(labelsList_.get(i).getId(), labelsList_.get(i).getName()));
}
}
else {
dialogLabels.dismiss();
Toasty.warning(ctx, getString(R.string.noLabelsFound));
}
labelsBinding.labelsRecyclerView.setAdapter(labelsAdapter);
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<List<Labels>> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
dialogLabels.show();
LabelsActions.getRepositoryLabels(ctx, instanceUrl, instanceToken, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
}
private void getBranches(String instanceUrl, String instanceToken, String repoOwner, String repoName, String loginUid) {

View File

@ -1,43 +1,48 @@
package org.mian.gitnex.activities;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
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.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.amulyakhare.textdrawable.TextDrawable;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.google.gson.JsonElement;
import com.vdurmont.emoji.EmojiParser;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.AssigneesActions;
import org.mian.gitnex.actions.LabelsActions;
import org.mian.gitnex.adapters.AssigneesListAdapter;
import org.mian.gitnex.adapters.IssueCommentsAdapter;
import org.mian.gitnex.adapters.LabelsListAdapter;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityIssueDetailBinding;
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
import org.mian.gitnex.databinding.CustomLabelsSelectionDialogBinding;
import org.mian.gitnex.fragments.BottomSheetSingleIssueFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
@ -48,15 +53,22 @@ import org.mian.gitnex.helpers.LabelWidthCalculator;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UserMentions;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.models.Collaborators;
import org.mian.gitnex.models.Issues;
import org.mian.gitnex.models.Labels;
import org.mian.gitnex.models.UpdateIssueAssignees;
import org.mian.gitnex.models.WatchInfo;
import org.mian.gitnex.viewmodels.IssueCommentsViewModel;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import io.noties.markwon.AbstractMarkwonPlugin;
@ -82,29 +94,36 @@ import retrofit2.Response;
* Author M M Arif
*/
public class IssueDetailActivity extends BaseActivity {
public class IssueDetailActivity extends BaseActivity implements LabelsListAdapter.LabelsListAdapterListener, AssigneesListAdapter.AssigneesListAdapterListener, BottomSheetSingleIssueFragment.BottomSheetListener {
public ImageView closeActivity;
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;
private ExtendedFloatingActionButton createNewComment;
final Context ctx = this;
private Context appCtx;
private LinearLayout labelsLayout;
private LinearLayout assigneesLayout;
private View divider;
private ProgressBar progressBar;
private ImageView issuePrState;
private TinyDB tinyDb;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repoOwner;
private String repoName;
private int issueIndex;
private LabelsListAdapter labelsAdapter;
private AssigneesListAdapter assigneesAdapter;
private List<Integer> currentLabelsIds = new ArrayList<>();
private List<Integer> labelsIds = new ArrayList<>();
private List<Labels> labelsList = new ArrayList<>();
private List<Collaborators> assigneesList = new ArrayList<>();
private List<String> assigneesListData = new ArrayList<>();
private List<String> currentAssignees = new ArrayList<>();
private Dialog dialogLabels;
private Dialog dialogAssignees;
private CustomLabelsSelectionDialogBinding labelsBinding;
private CustomAssigneesSelectionDialogBinding assigneesBinding;
private ActivityIssueDetailBinding viewBinding;
@Override
protected int getLayoutResourceId() {
@ -117,80 +136,65 @@ public class IssueDetailActivity extends BaseActivity {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
final TinyDB tinyDb = new TinyDB(appCtx);
viewBinding = ActivityIssueDetailBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
final String instanceUrl = tinyDb.getString("instanceUrl");
final String loginUid = tinyDb.getString("loginUid");
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
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"));
repoOwner = parts[0];
repoName = parts[1];
issueIndex = Integer.parseInt(tinyDb.getString("issueNumber"));
final SwipeRefreshLayout swipeRefresh = findViewById(R.id.pullToRefresh);
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);
createNewComment = findViewById(R.id.addNewComment);
labelsLayout = findViewById(R.id.frameLabels);
assigneesLayout = findViewById(R.id.frameAssignees);
divider = findViewById(R.id.divider);
progressBar = findViewById(R.id.progressBar);
issuePrState = findViewById(R.id.issuePrState);
Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar);
setSupportActionBar(viewBinding.toolbar);
Objects.requireNonNull(getSupportActionBar()).setTitle(repoName);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx));
viewBinding.recyclerView.setHasFixedSize(true);
viewBinding.recyclerView.setNestedScrollingEnabled(false);
viewBinding.recyclerView.setLayoutManager(new LinearLayoutManager(ctx));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(viewBinding.recyclerView.getContext(), DividerItemDecoration.VERTICAL);
viewBinding.recyclerView.addItemDecoration(dividerItemDecoration);
createNewComment.setOnClickListener(v -> startActivity(new Intent(ctx, ReplyToIssueActivity.class)));
viewBinding.addNewComment.setOnClickListener(v -> startActivity(new Intent(ctx, ReplyToIssueActivity.class)));
labelsAdapter = new LabelsListAdapter(labelsList, IssueDetailActivity.this, currentLabelsIds);
assigneesAdapter = new AssigneesListAdapter(ctx, assigneesList, IssueDetailActivity.this, currentAssignees);
LabelsActions.getCurrentIssueLabels(ctx, instanceUrl, loginUid, instanceToken, repoOwner, repoName, issueIndex, currentLabelsIds);
AssigneesActions.getCurrentIssueAssignees(ctx, instanceUrl, loginUid, instanceToken, repoOwner, repoName, issueIndex, currentAssignees);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
scrollViewComments.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
viewBinding.scrollViewComments.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
if((scrollY - oldScrollY) > 0 && createNewComment.isShown()) {
createNewComment.setVisibility(View.GONE);
if((scrollY - oldScrollY) > 0 && viewBinding.addNewComment.isShown()) {
viewBinding.addNewComment.setVisibility(View.GONE);
}
else if((scrollY - oldScrollY) < 0) {
createNewComment.setVisibility(View.VISIBLE);
viewBinding.addNewComment.setVisibility(View.VISIBLE);
}
if(!scrollViewComments.canScrollVertically(1)) { // bottom
createNewComment.setVisibility(View.GONE);
if(!viewBinding.scrollViewComments.canScrollVertically(1)) { // bottom
viewBinding.addNewComment.setVisibility(View.GONE);
}
if(!scrollViewComments.canScrollVertically(-1)) { // top
createNewComment.setVisibility(View.VISIBLE);
if(!viewBinding.scrollViewComments.canScrollVertically(-1)) { // top
viewBinding.addNewComment.setVisibility(View.VISIBLE);
}
});
}
swipeRefresh.setOnRefreshListener(() -> new Handler().postDelayed(() -> {
viewBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
swipeRefresh.setRefreshing(false);
viewBinding.pullToRefresh.setRefreshing(false);
IssueCommentsViewModel
.loadIssueComments(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex,
ctx);
@ -215,14 +219,231 @@ public class IssueDetailActivity extends BaseActivity {
}
toolbarTitle.setTypeface(myTypeface);
toolbarTitle.setText(repoName);
viewBinding.toolbarTitle.setTypeface(myTypeface);
viewBinding.toolbarTitle.setText(repoName);
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
fetchDataAsync(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
}
@Override
public void onButtonClicked(String text) {
switch(text) {
case "showLabels":
showLabels();
break;
case "showAssignees":
showAssignees();
break;
}
}
@Override
public void labelsInterface(List<String> data) {
}
@Override
public void labelsIdsInterface(List<Integer> data) {
labelsIds = data;
}
@Override
public void assigneesInterface(List<String> data) {
assigneesListData = data;
}
private void showAssignees() {
assigneesAdapter.updateList(currentAssignees);
dialogAssignees = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
dialogAssignees.setCancelable(false);
if (dialogAssignees.getWindow() != null) {
dialogAssignees.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
assigneesBinding = CustomAssigneesSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
View view = assigneesBinding.getRoot();
dialogAssignees.setContentView(view);
assigneesBinding.cancel.setOnClickListener(assigneesBinding_ -> {
currentAssignees = new ArrayList<>(new LinkedHashSet<>(currentAssignees));
assigneesListData = new ArrayList<>(new LinkedHashSet<>(assigneesListData));
Collections.sort(assigneesListData);
Collections.sort(currentAssignees);
if(!assigneesListData.equals(currentAssignees)) {
updateIssueAssignees();
}
else {
dialogAssignees.dismiss();
}
});
AssigneesActions.getRepositoryAssignees(ctx, instanceUrl, instanceToken, repoOwner, repoName, assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
}
public void showLabels() {
labelsAdapter.updateList(currentLabelsIds);
dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
dialogLabels.setCancelable(false);
if (dialogLabels.getWindow() != null) {
dialogLabels.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
labelsBinding = CustomLabelsSelectionDialogBinding.inflate(LayoutInflater.from(ctx));
View view = labelsBinding.getRoot();
dialogLabels.setContentView(view);
labelsBinding.cancel.setOnClickListener(labelsBinding_ -> {
currentLabelsIds = new ArrayList<>(new LinkedHashSet<>(currentLabelsIds));
labelsIds = new ArrayList<>(new LinkedHashSet<>(labelsIds));
Collections.sort(labelsIds);
Collections.sort(currentLabelsIds);
if(!labelsIds.equals(currentLabelsIds)) {
updateIssueLabels();
}
else {
dialogLabels.dismiss();
}
});
LabelsActions.getRepositoryLabels(ctx, instanceUrl, instanceToken, repoOwner, repoName, labelsList, dialogLabels, labelsAdapter, labelsBinding);
}
private void updateIssueAssignees() {
UpdateIssueAssignees updateAssigneeJson = new UpdateIssueAssignees(assigneesListData);
Call<JsonElement> call3;
call3 = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.patchIssueAssignees(Authorization.returnAuthentication(ctx, 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.success(ctx, ctx.getString(R.string.assigneesUpdated));
dialogAssignees.dismiss();
viewBinding.frameAssignees.removeAllViews();
viewBinding.frameLabels.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
currentAssignees.clear();
new Handler(Looper.getMainLooper()).postDelayed(() -> AssigneesActions.getCurrentIssueAssignees(ctx, instanceUrl, loginUid, instanceToken, repoOwner, repoName, issueIndex, currentAssignees), 1000);
}
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.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response2.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
private void updateIssueLabels() {
Labels patchIssueLabels = new Labels(labelsIds);
Call<JsonElement> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.updateIssueLabels(Authorization.returnAuthentication(ctx, 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.success(ctx, ctx.getString(R.string.labelsUpdated));
dialogLabels.dismiss();
viewBinding.frameAssignees.removeAllViews();
viewBinding.frameLabels.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
currentLabelsIds.clear();
new Handler(Looper.getMainLooper()).postDelayed(() -> LabelsActions.getCurrentIssueLabels(ctx, instanceUrl, loginUid, instanceToken, repoOwner, repoName, issueIndex, currentLabelsIds), 1000);
}
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.error(ctx, ctx.getString(R.string.authorizeError));
}
else if(response.code() == 404) {
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound));
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Log.e("onFailure", t.toString());
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
@ -254,24 +475,15 @@ public class IssueDetailActivity extends BaseActivity {
public void onResume() {
super.onResume();
final TinyDB tinyDb = new TinyDB(appCtx);
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(() -> {
viewBinding.scrollViewComments.post(() -> {
IssueCommentsViewModel
.loadIssueComments(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex,
ctx);
new Handler().postDelayed(() -> scrollViewComments.fullScroll(ScrollView.FOCUS_DOWN), 1000);
new Handler(Looper.getMainLooper()).postDelayed(() -> viewBinding.scrollViewComments.fullScroll(ScrollView.FOCUS_DOWN), 1000);
tinyDb.putBoolean("commentPosted", false);
@ -279,7 +491,7 @@ public class IssueDetailActivity extends BaseActivity {
}
if(tinyDb.getBoolean("commentEdited")) {
scrollViewComments.post(() -> {
viewBinding.scrollViewComments.post(() -> {
IssueCommentsViewModel
.loadIssueComments(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repoOwner, repoName, issueIndex,
@ -291,10 +503,10 @@ public class IssueDetailActivity extends BaseActivity {
if(tinyDb.getBoolean("singleIssueUpdate")) {
new Handler().postDelayed(() -> {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
assigneesLayout.removeAllViews();
labelsLayout.removeAllViews();
viewBinding.frameAssignees.removeAllViews();
viewBinding.frameLabels.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
tinyDb.putBoolean("singleIssueUpdate", false);
@ -304,10 +516,10 @@ public class IssueDetailActivity extends BaseActivity {
if(tinyDb.getBoolean("issueEdited")) {
new Handler().postDelayed(() -> {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
assigneesLayout.removeAllViews();
labelsLayout.removeAllViews();
viewBinding.frameAssignees.removeAllViews();
viewBinding.frameLabels.removeAllViews();
getSingleIssue(instanceUrl, instanceToken, repoOwner, repoName, issueIndex, loginUid);
tinyDb.putBoolean("issueEdited", false);
@ -327,11 +539,11 @@ public class IssueDetailActivity extends BaseActivity {
assert issueCommentsMain != null;
if(issueCommentsMain.size() > 0) {
divider.setVisibility(View.VISIBLE);
viewBinding.divider.setVisibility(View.VISIBLE);
}
adapter = new IssueCommentsAdapter(ctx, issueCommentsMain);
mRecyclerView.setAdapter(adapter);
viewBinding.recyclerView.setAdapter(adapter);
});
@ -353,25 +565,25 @@ public class IssueDetailActivity extends BaseActivity {
Issues singleIssue = response.body();
assert singleIssue != null;
issuePrState.setVisibility(View.VISIBLE);
viewBinding.issuePrState.setVisibility(View.VISIBLE);
if(singleIssue.getPull_request() != null) {
if(singleIssue.getPull_request().isMerged()) { // merged
issuePrState.setImageResource(R.drawable.ic_pull_request_merged);
viewBinding.issuePrState.setImageResource(R.drawable.ic_pull_request_merged);
}
else if(!singleIssue.getPull_request().isMerged() && singleIssue.getState().equals("closed")) { // closed
issuePrState.setImageResource(R.drawable.ic_pull_request_closed);
viewBinding.issuePrState.setImageResource(R.drawable.ic_pull_request_closed);
}
else { // open
issuePrState.setImageResource(R.drawable.ic_pull_request);
viewBinding.issuePrState.setImageResource(R.drawable.ic_pull_request);
}
}
else if(singleIssue.getState().equals("closed")) { // issue closed
issuePrState.setImageResource(R.drawable.ic_issue_closed_red);
viewBinding.issuePrState.setImageResource(R.drawable.ic_issue_closed_red);
}
final Markwon markwon = Markwon.builder(Objects.requireNonNull(ctx)).usePlugin(CorePlugin.create())
@ -424,21 +636,21 @@ public class IssueDetailActivity extends BaseActivity {
tinyDb.putString("singleIssueHtmlUrl", singleIssue.getHtml_url());
PicassoService.getInstance(ctx).get().load(singleIssue.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated)
.transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(assigneeAvatar);
.transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(viewBinding.assigneeAvatar);
String issueNumber_ = "<font color='" + appCtx.getResources().getColor(R.color.lightGray) + "'>" + appCtx.getResources()
.getString(R.string.hash) + singleIssue.getNumber() + "</font>";
issueTitle.setText(Html.fromHtml(issueNumber_ + " " + singleIssue.getTitle()));
viewBinding.issueTitle.setText(Html.fromHtml(issueNumber_ + " " + singleIssue.getTitle()));
String cleanIssueDescription = singleIssue.getBody().trim();
Spanned bodyWithMD = markwon.toMarkdown(EmojiParser.parseToUnicode(cleanIssueDescription));
markwon.setParsedMarkdown(issueDescription, UserMentions.UserMentionsFunc(ctx, bodyWithMD, cleanIssueDescription));
markwon.setParsedMarkdown(viewBinding.issueDescription, UserMentions.UserMentionsFunc(ctx, bodyWithMD, cleanIssueDescription));
RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams) issueDescription.getLayoutParams();
RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams) viewBinding.issueDescription.getLayoutParams();
LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(80, 80);
params1.setMargins(15, 0, 0, 0);
if(singleIssue.getAssignees() != null) {
assigneesScrollView.setVisibility(View.VISIBLE);
viewBinding.assigneesScrollView.setVisibility(View.VISIBLE);
for(int i = 0; i < singleIssue.getAssignees().size(); i++) {
ImageView assigneesView = new ImageView(ctx);
@ -447,7 +659,7 @@ public class IssueDetailActivity extends BaseActivity {
.placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(100, 100).centerCrop()
.into(assigneesView);
assigneesLayout.addView(assigneesView);
viewBinding.frameAssignees.addView(assigneesView);
assigneesView.setLayoutParams(params1);
if(!singleIssue.getAssignees().get(i).getFull_name().equals("")) {
assigneesView.setOnClickListener(
@ -461,7 +673,7 @@ public class IssueDetailActivity extends BaseActivity {
}
}
else {
assigneesScrollView.setVisibility(View.GONE);
viewBinding.assigneesScrollView.setVisibility(View.GONE);
}
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
@ -469,7 +681,7 @@ public class IssueDetailActivity extends BaseActivity {
params.setMargins(0, 0, 15, 0);
if(singleIssue.getLabels() != null) {
labelsScrollView.setVisibility(View.VISIBLE);
viewBinding.labelsScrollView.setVisibility(View.VISIBLE);
for(int i = 0; i < singleIssue.getLabels().size(); i++) {
@ -478,8 +690,8 @@ public class IssueDetailActivity extends BaseActivity {
int color = Color.parseColor("#" + labelColor);
ImageView labelsView = new ImageView(ctx);
labelsLayout.setOrientation(LinearLayout.HORIZONTAL);
labelsLayout.setGravity(Gravity.START | Gravity.TOP);
viewBinding.frameLabels.setOrientation(LinearLayout.HORIZONTAL);
viewBinding.frameLabels.setGravity(Gravity.START | Gravity.TOP);
labelsView.setLayoutParams(params);
int height = AppUtil.getPixelsFromDensity(ctx, 25);
@ -491,12 +703,12 @@ public class IssueDetailActivity extends BaseActivity {
.height(height).endConfig().buildRoundRect(labelName, color, AppUtil.getPixelsFromDensity(ctx, 5));
labelsView.setImageDrawable(drawable);
labelsLayout.addView(labelsView);
viewBinding.frameLabels.addView(labelsView);
}
}
else {
labelsScrollView.setVisibility(View.GONE);
viewBinding.labelsScrollView.setVisibility(View.GONE);
}
if(singleIssue.getDue_date() != null) {
@ -504,77 +716,77 @@ public class IssueDetailActivity extends BaseActivity {
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(dueDate);
issueDueDate
viewBinding.issueDueDate.setText(dueDate);
viewBinding.issueDueDate
.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getDue_date()), ctx));
}
else if(timeFormat.equals("normal1")) {
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy", new Locale(locale));
String dueDate = formatter.format(singleIssue.getDue_date());
issueDueDate.setText(dueDate);
viewBinding.issueDueDate.setText(dueDate);
}
}
else {
issueDueDate.setVisibility(View.GONE);
viewBinding.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
viewBinding.issueModified.setVisibility(View.VISIBLE);
viewBinding.issueModified.setText(edited);
viewBinding.issueModified
.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getUpdated_at()), ctx));
}
else {
issueModified.setVisibility(View.INVISIBLE);
viewBinding.issueModified.setVisibility(View.INVISIBLE);
}
if((singleIssue.getDue_date() == null && singleIssue.getMilestone() == null) && singleIssue.getAssignees() != null) {
paramsDesc.setMargins(0, 35, 0, 0);
issueDescription.setLayoutParams(paramsDesc);
viewBinding.issueDescription.setLayoutParams(paramsDesc);
}
else if(singleIssue.getDue_date() == null && singleIssue.getMilestone() == null) {
paramsDesc.setMargins(0, 55, 0, 0);
issueDescription.setLayoutParams(paramsDesc);
viewBinding.issueDescription.setLayoutParams(paramsDesc);
}
else if(singleIssue.getAssignees() == null) {
paramsDesc.setMargins(0, 35, 0, 0);
issueDescription.setLayoutParams(paramsDesc);
viewBinding.issueDescription.setLayoutParams(paramsDesc);
}
else {
paramsDesc.setMargins(0, 15, 0, 0);
issueDescription.setLayoutParams(paramsDesc);
viewBinding.issueDescription.setLayoutParams(paramsDesc);
}
issueCreatedTime.setText(TimeHelper.formatTime(singleIssue.getCreated_at(), new Locale(locale), timeFormat, ctx));
issueCreatedTime.setVisibility(View.VISIBLE);
viewBinding.issueCreatedTime.setText(TimeHelper.formatTime(singleIssue.getCreated_at(), new Locale(locale), timeFormat, ctx));
viewBinding.issueCreatedTime.setVisibility(View.VISIBLE);
if(timeFormat.equals("pretty")) {
issueCreatedTime
viewBinding.issueCreatedTime
.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(singleIssue.getCreated_at()), ctx));
}
if(singleIssue.getMilestone() != null) {
issueMilestone.setText(getString(R.string.issueMilestone, singleIssue.getMilestone().getTitle()));
viewBinding.issueMilestone.setText(getString(R.string.issueMilestone, singleIssue.getMilestone().getTitle()));
}
else {
issueMilestone.setVisibility(View.GONE);
viewBinding.issueMilestone.setVisibility(View.GONE);
}
if(!singleIssue.getUser().getFull_name().equals("")) {
assigneeAvatar.setOnClickListener(
viewBinding.assigneeAvatar.setOnClickListener(
new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getFull_name(), ctx));
}
else {
assigneeAvatar.setOnClickListener(
viewBinding.assigneeAvatar.setOnClickListener(
new ClickListener(ctx.getResources().getString(R.string.issueCreator) + singleIssue.getUser().getLogin(), ctx));
}
progressBar.setVisibility(View.GONE);
viewBinding.progressBar.setVisibility(View.GONE);
}

View File

@ -4,19 +4,16 @@ import android.content.Context;
import android.content.Intent;
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.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import com.tooltip.Tooltip;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.UserAccountsApi;
@ -82,7 +79,6 @@ public class LoginActivity extends BaseActivity {
loginPassword = findViewById(R.id.login_passwd);
otpCode = findViewById(R.id.otpCode);
otpInfo = findViewById(R.id.otpInfo);
ImageView info_button = findViewById(R.id.info);
protocolSpinner = findViewById(R.id.httpsSpinner);
loginMethod = findViewById(R.id.loginMethod);
loginTokenCode = findViewById(R.id.loginTokenCode);
@ -108,11 +104,6 @@ public class LoginActivity extends BaseActivity {
});
info_button.setOnClickListener(
view -> new Tooltip.Builder(view).setText(R.string.urlInfoTooltip).setTextColor(getResources().getColor(R.color.colorWhite))
.setBackgroundColor(getResources().getColor(R.color.tooltipBackground)).setCancelable(true).setDismissOnClick(true).setPadding(30)
.setCornerRadius(R.dimen.tooltipCornor).setGravity(Gravity.BOTTOM).show());
loginMethod.setOnCheckedChangeListener((group, checkedId) -> {
if(checkedId == R.id.loginToken) {

View File

@ -0,0 +1,130 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.models.Collaborators;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
/**
* Author M M Arif
*/
public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdapter.AssigneesViewHolder> {
private Context mCtx;
private List<Collaborators> assigneesList;
private List<String> assigneesStrings = new ArrayList<>();
private List<String> currentAssignees;
private AssigneesListAdapterListener assigneesListener;
public interface AssigneesListAdapterListener {
void assigneesInterface(List<String> data);
}
public AssigneesListAdapter(Context mCtx, List<Collaborators> dataMain, AssigneesListAdapterListener assigneesListener, List<String> currentAssignees) {
this.mCtx = mCtx;
this.assigneesList = dataMain;
this.assigneesListener = assigneesListener;
this.currentAssignees = currentAssignees;
}
static class AssigneesViewHolder extends RecyclerView.ViewHolder {
private CheckBox assigneesSelection;
private TextView assigneesName;
private ImageView assigneesAvatar;
private AssigneesViewHolder(View itemView) {
super(itemView);
assigneesSelection = itemView.findViewById(R.id.assigneesSelection);
assigneesName = itemView.findViewById(R.id.assigneesName);
assigneesAvatar = itemView.findViewById(R.id.assigneesAvatar);
}
}
@NonNull
@Override
public AssigneesListAdapter.AssigneesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_assignees_list, parent, false);
return new AssigneesListAdapter.AssigneesViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull AssigneesListAdapter.AssigneesViewHolder holder, int position) {
Collaborators currentItem = assigneesList.get(position);
if(currentItem.getFull_name().equals("")) {
holder.assigneesName.setText(currentItem.getLogin());
}
else {
holder.assigneesName.setText(currentItem.getFull_name());
}
PicassoService
.getInstance(mCtx).get().load(currentItem.getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(180, 180).centerCrop().into(holder.assigneesAvatar);
for(int i = 0; i < assigneesList.size(); i++) {
if(assigneesStrings.contains(currentItem.getLogin())) {
holder.assigneesSelection.setChecked(true);
}
}
currentAssignees = new ArrayList<>(new LinkedHashSet<>(currentAssignees));
for(int i = 0; i < currentAssignees.size(); i++) {
if(currentAssignees.contains(currentItem.getLogin())) {
holder.assigneesSelection.setChecked(true);
assigneesStrings.add(currentAssignees.get(i));
}
}
assigneesListener.assigneesInterface(assigneesStrings);
holder.assigneesSelection.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
assigneesStrings.add(currentItem.getLogin());
}
else {
assigneesStrings.remove(currentItem.getLogin());
}
assigneesListener.assigneesInterface(assigneesStrings);
});
assigneesStrings = new ArrayList<>(new LinkedHashSet<>(assigneesStrings));
}
@Override
public int getItemCount() {
return assigneesList.size();
}
public void updateList(List<String> list) {
currentAssignees = list;
notifyDataSetChanged();
}
}

View File

@ -1,14 +1,18 @@
package org.mian.gitnex.adapters;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.models.Labels;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
/**
@ -17,32 +21,38 @@ import java.util.List;
public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.LabelsViewHolder> {
private List<Integer> currentLabelsIds;
private List<Labels> labels;
private ArrayList<String> labelsStrings = new ArrayList<>();
private ArrayList<Integer> labelsIds = new ArrayList<>();
private List<String> labelsStrings = new ArrayList<>();
private List<Integer> labelsIds = new ArrayList<>();
private LabelsListAdapterListener labelsListener;
public interface LabelsListAdapterListener {
void labelsStringData(ArrayList<String> data);
void labelsIdsData(ArrayList<Integer> data);
void labelsInterface(List<String> data);
void labelsIdsInterface(List<Integer> data);
}
public LabelsListAdapter(List<Labels> labelsMain, LabelsListAdapterListener labelsListener) {
public LabelsListAdapter(List<Labels> labelsMain, LabelsListAdapterListener labelsListener, List<Integer> currentLabelsIds) {
this.labels = labelsMain;
this.labelsListener = labelsListener;
this.currentLabelsIds = currentLabelsIds;
}
static class LabelsViewHolder extends RecyclerView.ViewHolder {
private CheckBox labelSelection;
private TextView labelText;
private ImageView labelColor;
private LabelsViewHolder(View itemView) {
super(itemView);
labelSelection = itemView.findViewById(R.id.labelSelection);
labelText = itemView.findViewById(R.id.labelText);
labelColor = itemView.findViewById(R.id.labelColor);
}
}
@ -60,7 +70,11 @@ public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.La
Labels currentItem = labels.get(position);
holder.labelSelection.setText(currentItem.getName());
String labelColor = currentItem.getColor();
int color = Color.parseColor("#" + labelColor);
holder.labelText.setText(currentItem.getName());
holder.labelColor.setBackgroundColor(color);
for(int i = 0; i < labelsIds.size(); i++) {
@ -70,6 +84,17 @@ public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.La
}
}
currentLabelsIds = new ArrayList<>(new LinkedHashSet<>(currentLabelsIds));
for(int i = 0; i < currentLabelsIds.size(); i++) {
if(currentLabelsIds.contains(currentItem.getId())) {
holder.labelSelection.setChecked(true);
labelsIds.add(currentLabelsIds.get(i));
}
}
labelsListener.labelsIdsInterface(labelsIds);
holder.labelSelection.setOnCheckedChangeListener((buttonView, isChecked) -> {
if(isChecked) {
@ -83,13 +108,21 @@ public class LabelsListAdapter extends RecyclerView.Adapter<LabelsListAdapter.La
labelsIds.remove(Integer.valueOf(currentItem.getId()));
}
labelsListener.labelsStringData(labelsStrings);
labelsListener.labelsIdsData(labelsIds);
labelsListener.labelsInterface(labelsStrings);
labelsListener.labelsIdsInterface(labelsIds);
});
labelsIds = new ArrayList<>(new LinkedHashSet<>(labelsIds));
}
@Override
public int getItemCount() {
return labels.size();
}
public void updateList(List<Integer> list) {
currentLabelsIds = list;
notifyDataSetChanged();
}
}

View File

@ -1,190 +0,0 @@
package org.mian.gitnex.adapters;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.TextAppearanceSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatCheckBox;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.helpers.MultiSelectDialog;
import org.mian.gitnex.models.MultiSelectModel;
import java.util.List;
/**
* Author com.github.abumoallim, modified by M M Arif
*/
public class MutliSelectAdapter extends RecyclerView.Adapter<MutliSelectAdapter.MultiSelectDialogViewHolder> {
private List<MultiSelectModel> mDataSet;
private String mSearchQuery = "";
private Context mContext;
public MutliSelectAdapter(List<MultiSelectModel> dataSet, Context context) {
this.mDataSet = dataSet;
this.mContext = context;
}
@NonNull
@Override
public MultiSelectDialogViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.multi_select_item, parent, false);
return new MultiSelectDialogViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final MultiSelectDialogViewHolder holder, int position) {
if (!mSearchQuery.equals("") && mSearchQuery.length() > 1) {
setHighlightedText(position, holder.dialog_name_item);
} else {
holder.dialog_name_item.setText(mDataSet.get(position).getName());
}
if (mDataSet.get(position).getSelected()) {
if (!MultiSelectDialog.selectedIdsForCallback.contains(mDataSet.get(position).getId())) {
MultiSelectDialog.selectedIdsForCallback.add(mDataSet.get(position).getId());
}
}
if (checkForSelection(mDataSet.get(position).getId())) {
holder.dialog_item_checkbox.setChecked(true);
} else {
holder.dialog_item_checkbox.setChecked(false);
}
/*holder.dialog_item_checkbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (holder.dialog_item_checkbox.isChecked()) {
MultiSelectDialog.selectedIdsForCallback.add(mDataSet.get(holder.getAdapterPosition()).getId());
holder.dialog_item_checkbox.setChecked(true);
} else {
removeFromSelection(mDataSet.get(holder.getAdapterPosition()).getId());
holder.dialog_item_checkbox.setChecked(false);
}
}
});*/
holder.main_container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!holder.dialog_item_checkbox.isChecked()) {
MultiSelectDialog.selectedIdsForCallback.add(mDataSet.get(holder.getAdapterPosition()).getId());
holder.dialog_item_checkbox.setChecked(true);
mDataSet.get(holder.getAdapterPosition()).setSelected(true);
notifyItemChanged(holder.getAdapterPosition());
} else {
removeFromSelection(mDataSet.get(holder.getAdapterPosition()).getId());
holder.dialog_item_checkbox.setChecked(false);
mDataSet.get(holder.getAdapterPosition()).setSelected(false);
notifyItemChanged(holder.getAdapterPosition());
}
}
});
}
private void setHighlightedText(int position, TextView textview) {
String name = mDataSet.get(position).getName();
SpannableString str = new SpannableString(name);
int endLength = name.toLowerCase().indexOf(mSearchQuery) + mSearchQuery.length();
ColorStateList highlightedColor = new ColorStateList(new int[][]{new int[]{}}, new int[]{ContextCompat.getColor(mContext, R.color.colorAccent)});
TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(null, Typeface.NORMAL, -1, highlightedColor, null);
str.setSpan(textAppearanceSpan, name.toLowerCase().indexOf(mSearchQuery), endLength, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(str);
}
private void removeFromSelection(Integer id) {
for (int i = 0; i < MultiSelectDialog.selectedIdsForCallback.size(); i++) {
if (id.equals(MultiSelectDialog.selectedIdsForCallback.get(i))) {
MultiSelectDialog.selectedIdsForCallback.remove(i);
}
}
}
private boolean checkForSelection(Integer id) {
for (int i = 0; i < MultiSelectDialog.selectedIdsForCallback.size(); i++) {
if (id.equals(MultiSelectDialog.selectedIdsForCallback.get(i))) {
return true;
}
}
return false;
}
/*//get selected name string separated by coma
public String getDataString() {
String data = "";
for (int i = 0; i < mDataSet.size(); i++) {
if (checkForSelection(mDataSet.get(i).getId())) {
data = data + ", " + mDataSet.get(i).getName();
}
}
if (data.length() > 0) {
return data.substring(1);
} else {
return "";
}
}
//get selected name ararylist
public ArrayList<String> getSelectedNameList() {
ArrayList<String> names = new ArrayList<>();
for (int i = 0; i < mDataSet.size(); i++) {
if (checkForSelection(mDataSet.get(i).getId())) {
names.add(mDataSet.get(i).getName());
}
}
// return names.toArray(new String[names.size()]);
return names;
}*/
@Override
public int getItemCount() {
return mDataSet.size();
}
public void setData(List<MultiSelectModel> data, String query, MutliSelectAdapter mutliSelectAdapter) {
this.mDataSet = data;
this.mSearchQuery = query;
mutliSelectAdapter.notifyDataSetChanged();
}
class MultiSelectDialogViewHolder extends RecyclerView.ViewHolder {
private TextView dialog_name_item;
private AppCompatCheckBox dialog_item_checkbox;
private LinearLayout main_container;
MultiSelectDialogViewHolder(View view) {
super(view);
dialog_name_item = view.findViewById(R.id.dialog_item_name);
dialog_item_checkbox = view.findViewById(R.id.dialog_item_checkbox);
main_container = view.findViewById(R.id.main_container);
}
}
}

View File

@ -14,8 +14,6 @@ import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.R;
import org.mian.gitnex.actions.IssueActions;
import org.mian.gitnex.activities.AddRemoveAssigneesActivity;
import org.mian.gitnex.activities.AddRemoveLabelsActivity;
import org.mian.gitnex.activities.EditIssueActivity;
import org.mian.gitnex.activities.FileDiffActivity;
import org.mian.gitnex.activities.MergePullRequestActivity;
@ -30,6 +28,8 @@ import java.util.Objects;
public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment {
private BottomSheetListener bmListener;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -78,42 +78,36 @@ public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment {
else {
mergePullRequest.setVisibility(View.GONE);
}
mergePullRequest.setOnClickListener(v13 -> {
startActivity(new Intent(ctx, MergePullRequestActivity.class));
dismiss();
});
openFilesDiff.setOnClickListener(v14 -> {
startActivity(new Intent(ctx, FileDiffActivity.class));
dismiss();
});
editIssue.setOnClickListener(v15 -> {
startActivity(new Intent(ctx, EditIssueActivity.class));
dismiss();
});
editLabels.setOnClickListener(v16 -> {
startActivity(new Intent(ctx, AddRemoveLabelsActivity.class));
bmListener.onButtonClicked("showLabels");
dismiss();
});
addRemoveAssignees.setOnClickListener(v17 -> {
startActivity(new Intent(ctx, AddRemoveAssigneesActivity.class));
bmListener.onButtonClicked("showAssignees");
dismiss();
});
shareIssue.setOnClickListener(v1 -> {
@ -125,7 +119,6 @@ public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment {
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.hash) + tinyDB.getString("issueNumber") + " " + tinyDB.getString("issueTitle")));
dismiss();
});
copyIssueUrl.setOnClickListener(v12 -> {
@ -139,7 +132,6 @@ public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment {
Toasty.info(ctx, ctx.getString(R.string.copyIssueUrlToastMsg));
dismiss();
});
if(tinyDB.getString("issueType").equalsIgnoreCase("Issue")) {
@ -183,14 +175,12 @@ public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment {
IssueActions.subscribe(ctx);
dismiss();
});
unsubscribeIssue.setOnClickListener(unsubscribeToIssue -> {
IssueActions.unsubscribe(ctx);
dismiss();
});
if(new Version(tinyDB.getString("giteaVersion")).less("1.12.0")) {
@ -209,4 +199,23 @@ public class BottomSheetSingleIssueFragment extends BottomSheetDialogFragment {
return v;
}
public interface BottomSheetListener {
void onButtonClicked(String text);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
bmListener = (BottomSheetListener) context;
}
catch(ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement BottomSheetListener");
}
}
}

View File

@ -207,17 +207,19 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
FilesViewModel filesModel = new ViewModelProvider(this).get(FilesViewModel.class);
filesModel.getFilesList(instanceUrl, instanceToken, owner, repo, ref, getContext()).observe(getViewLifecycleOwner(), filesListMain -> {
filesModel.getFilesList(instanceUrl, instanceToken, owner, repo, ref, getContext(), mProgressBar, noDataFiles).observe(getViewLifecycleOwner(), filesListMain -> {
adapter = new FilesAdapter(getContext(), filesListMain, FilesFragment.this);
mBreadcrumbsView.removeItemAfter(1);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame);
noDataFiles.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
AppUtil.setMultiVisibility(View.VISIBLE, mRecyclerView, filesFrame, noDataFiles);
@ -225,7 +227,6 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
filesFrame.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
});
}
@ -237,7 +238,7 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
FilesViewModel filesModel2 = new ViewModelProvider(this).get(FilesViewModel.class);
filesModel2.getFilesList2(instanceUrl, instanceToken, owner, repo, filesDir, ref, getContext()).observe(this, filesListMain2 -> {
filesModel2.getFilesList2(instanceUrl, instanceToken, owner, repo, filesDir, ref, getContext(), mProgressBar, noDataFiles).observe(this, filesListMain2 -> {
adapter = new FilesAdapter(getContext(), filesListMain2, FilesFragment.this);

View File

@ -1,318 +0,0 @@
package org.mian.gitnex.helpers;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.MutliSelectAdapter;
import org.mian.gitnex.models.MultiSelectModel;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Author com.github.abumoallim, modified by M M Arif
*/
public class MultiSelectDialog extends AppCompatDialogFragment implements SearchView.OnQueryTextListener, View.OnClickListener {
public static List<Integer> selectedIdsForCallback = new ArrayList<>();
public List<MultiSelectModel> mainListOfAdapter = new ArrayList<>();
private MutliSelectAdapter mutliSelectAdapter;
//Default Values
private String title;
private float titleSize = 25;
private String positiveText = "DONE";
private String negativeText = "CANCEL";
private TextView dialogTitle, dialogSubmit, dialogCancel;
private List<Integer> previouslySelectedIdsList = new ArrayList<>();
private List<Integer> tempPreviouslySelectedIdsList = new ArrayList<>();
private List<MultiSelectModel> tempMainListOfAdapter = new ArrayList<>();
private SubmitCallbackListener submitCallbackListener;
private int minSelectionLimit = 1;
private String minSelectionMessage = null;
private int maxSelectionLimit = 0;
private String maxSelectionMessage = null;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Dialog dialog = new Dialog(Objects.requireNonNull(getActivity()));
Objects.requireNonNull(dialog.getWindow()).requestFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setFlags(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
dialog.setContentView(R.layout.custom_multi_select);
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
RecyclerViewEmptySupport mrecyclerView = dialog.findViewById(R.id.recycler_view);
SearchView searchView = dialog.findViewById(R.id.search_view);
dialogTitle = dialog.findViewById(R.id.title);
dialogSubmit = dialog.findViewById(R.id.done);
dialogCancel = dialog.findViewById(R.id.cancel);
mrecyclerView.setEmptyView(dialog.findViewById(R.id.list_empty1));
@SuppressLint("WrongConstant") LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
mrecyclerView.setLayoutManager(layoutManager);
dialogSubmit.setOnClickListener(this);
dialogCancel.setOnClickListener(this);
settingValues();
mainListOfAdapter = setCheckedIDS(mainListOfAdapter, previouslySelectedIdsList);
mutliSelectAdapter = new MutliSelectAdapter(mainListOfAdapter, getContext());
mrecyclerView.setAdapter(mutliSelectAdapter);
searchView.setOnQueryTextListener(this);
searchView.onActionViewExpanded();
searchView.clearFocus();
return dialog;
}
public MultiSelectDialog title(String title) {
this.title = title;
return this;
}
public MultiSelectDialog titleSize(float titleSize) {
this.titleSize = titleSize;
return this;
}
public MultiSelectDialog positiveText(@NonNull String message) {
this.positiveText = message;
return this;
}
public MultiSelectDialog negativeText(@NonNull String message) {
this.negativeText = message;
return this;
}
public MultiSelectDialog preSelectIDsList(List<Integer> list) {
this.previouslySelectedIdsList = list;
this.tempPreviouslySelectedIdsList = new ArrayList<>(previouslySelectedIdsList);
return this;
}
public MultiSelectDialog multiSelectList(List<MultiSelectModel> list) {
this.mainListOfAdapter = list;
this.tempMainListOfAdapter = new ArrayList<>(mainListOfAdapter);
if(maxSelectionLimit == 0)
maxSelectionLimit = list.size();
return this;
}
public MultiSelectDialog setMaxSelectionLimit(int limit){
this.maxSelectionLimit = limit;
return this;
}
public MultiSelectDialog setMaxSelectionMessage(String message) {
this.maxSelectionMessage = message;
return this;
}
public MultiSelectDialog setMinSelectionLimit(int limit){
this.minSelectionLimit = limit;
return this;
}
public MultiSelectDialog setMinSelectionMessage(String message) {
this.minSelectionMessage = message;
return this;
}
public MultiSelectDialog onSubmit(@NonNull SubmitCallbackListener callback) {
this.submitCallbackListener = callback;
return this;
}
private void settingValues() {
dialogTitle.setText(title);
dialogTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, titleSize);
dialogSubmit.setText(positiveText.toUpperCase());
dialogCancel.setText(negativeText.toUpperCase());
}
private List<MultiSelectModel> setCheckedIDS(List<MultiSelectModel> multiselectdata, List<Integer> listOfIdsSelected) {
for (int i = 0; i < multiselectdata.size(); i++) {
multiselectdata.get(i).setSelected(false);
for (int j = 0; j < listOfIdsSelected.size(); j++) {
if (listOfIdsSelected.get(j) == (multiselectdata.get(i).getId())) {
multiselectdata.get(i).setSelected(true);
}
}
}
return multiselectdata;
}
private List<MultiSelectModel> filter(List<MultiSelectModel> models, String query) {
query = query.toLowerCase();
final List<MultiSelectModel> filteredModelList = new ArrayList<>();
if (query.equals("") | query.isEmpty()) {
filteredModelList.addAll(models);
return filteredModelList;
}
for (MultiSelectModel model : models) {
final String name = model.getName().toLowerCase();
if (name.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
selectedIdsForCallback = previouslySelectedIdsList;
mainListOfAdapter = setCheckedIDS(mainListOfAdapter, selectedIdsForCallback);
List<MultiSelectModel> filteredlist = filter(mainListOfAdapter, newText);
mutliSelectAdapter.setData(filteredlist, newText.toLowerCase(), mutliSelectAdapter);
return false;
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.done) {
List<Integer> callBackListOfIds = selectedIdsForCallback;
if (callBackListOfIds.size() >= minSelectionLimit) {
if (callBackListOfIds.size() <= maxSelectionLimit) {
//to remember last selected ids which were successfully done
tempPreviouslySelectedIdsList = new ArrayList<>(callBackListOfIds);
if(submitCallbackListener !=null) {
submitCallbackListener.onSelected(callBackListOfIds, getSelectNameList(), getSelectedDataString());
}
dismiss();
} else {
String youCan = getResources().getString(R.string.you_can_only_select_upto);
String options = getResources().getString(R.string.options);
String option = getResources().getString(R.string.option);
String message = "";
if(this.maxSelectionMessage != null) {
message = maxSelectionMessage;
}
else {
if (maxSelectionLimit > 1)
message = youCan + " " + maxSelectionLimit + " " + options;
else
message = youCan + " " + maxSelectionLimit + " " + option;
}
Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
}
} else {
String pleaseSelect = getResources().getString(R.string.please_select_atleast);
String options = getResources().getString(R.string.options);
String option = getResources().getString(R.string.option);
String message = "";
if(this.minSelectionMessage != null) {
message = minSelectionMessage;
}
else {
if (minSelectionLimit > 1)
message = pleaseSelect + " " + minSelectionLimit + " " + options;
else
message = pleaseSelect + " " + minSelectionLimit + " " + option;
}
Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
}
}
if (view.getId() == R.id.cancel) {
if(submitCallbackListener!=null){
selectedIdsForCallback.clear();
selectedIdsForCallback.addAll(tempPreviouslySelectedIdsList);
submitCallbackListener.onCancel();
}
dismiss();
}
}
private String getSelectedDataString() {
String data = "";
for (int i = 0; i < tempMainListOfAdapter.size(); i++) {
if (checkForSelection(tempMainListOfAdapter.get(i).getId())) {
data = data + ", " + tempMainListOfAdapter.get(i).getName();
}
}
if (data.length() > 0) {
return data.substring(1);
} else {
return "";
}
}
private List<String> getSelectNameList() {
List<String> names = new ArrayList<>();
for(int i=0;i<tempMainListOfAdapter.size();i++){
if(checkForSelection(tempMainListOfAdapter.get(i).getId())){
names.add(tempMainListOfAdapter.get(i).getName());
}
}
return names;
}
private boolean checkForSelection(Integer id) {
for (int i = 0; i < MultiSelectDialog.selectedIdsForCallback.size(); i++) {
if (id.equals(MultiSelectDialog.selectedIdsForCallback.get(i))) {
return true;
}
}
return false;
}
/* public void setCallbackListener(SubmitCallbackListener submitCallbackListener) {
this.submitCallbackListener = submitCallbackListener;
}*/
public interface SubmitCallbackListener {
void onSelected(List<Integer> selectedIds, List<String> selectedNames, String commonSeperatedData);
void onCancel();
}
}

View File

@ -163,6 +163,9 @@ public interface ApiInterface {
@GET("repos/{owner}/{repo}/collaborators") // get collaborators list
Call<List<Collaborators>> getCollaborators(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@GET("orgs/{org}/members") // get organization members
Call<List<Collaborators>> getOrgMembers(@Header("Authorization") String token, @Path("org") String ownerName);
@POST("repos/{owner}/{repo}/milestones") // create new milestone
Call<Milestones> createMilestone(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Body Milestones jsonStr);

View File

@ -1,5 +1,7 @@
package org.mian.gitnex.models;
import java.util.Objects;
/**
* Author M M Arif
*/
@ -14,6 +16,13 @@ public class Collaborators {
private String language;
private String username;
public Collaborators(String full_name, String login, String avatar_url) {
this.full_name = full_name;
this.login = login;
this.avatar_url = avatar_url;
}
public int getId() {
return id;
}
@ -41,4 +50,24 @@ public class Collaborators {
public String getUsername() {
return username;
}
@Override
public boolean equals(Object o) {
if(this == o) {
return true;
}
if(o == null || getClass() != o.getClass()) {
return false;
}
Collaborators that = (Collaborators) o;
return Objects.equals(login, that.login);
}
@Override
public int hashCode() {
return Objects.hash(login);
}
}

View File

@ -15,9 +15,9 @@ public class CreateIssue {
private String title;
private List<String> assignees;
private int[] labels;
private List<Integer> labels;
public CreateIssue(String assignee, String body, boolean closed, String due_date, int milestone, String title, List<String> assignees, int[] labels) {
public CreateIssue(String assignee, String body, boolean closed, String due_date, int milestone, String title, List<String> assignees, List<Integer> labels) {
this.body = body;
this.closed = closed;
this.due_date = due_date;

View File

@ -1,6 +1,6 @@
package org.mian.gitnex.models;
import java.util.ArrayList;
import java.util.List;
/**
* Author M M Arif
@ -17,10 +17,10 @@ public class CreatePullRequest {
private String due_date;
private String message;
private ArrayList<String> assignees;
private ArrayList<Integer> labels;
private List<String> assignees;
private List<Integer> labels;
public CreatePullRequest(String title, String body, String assignee, String base, String head, int milestone, String due_date, ArrayList<String> assignees, ArrayList<Integer> labels) {
public CreatePullRequest(String title, String body, String assignee, String base, String head, int milestone, String due_date, List<String> assignees, List<Integer> labels) {
this.title = title;
this.body = body;

View File

@ -1,5 +1,7 @@
package org.mian.gitnex.models;
import java.util.List;
/**
* Author M M Arif
*/
@ -10,20 +12,21 @@ public class Labels {
private String name;
private String color;
private String url;
private int[] labels;
private List<Integer> labels;
public Labels(String name, String color) {
this.name = name;
this.color = color;
}
public Labels(int[] labels) {
public Labels(List<Integer> labels) {
this.labels = labels;
}
public Labels(int id, String name) {
public Labels(int id, String name, String color) {
this.id = id;
this.name = name;
this.color = color;
}
public int getId() {

View File

@ -1,7 +1,9 @@
package org.mian.gitnex.viewmodels;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
@ -25,15 +27,15 @@ public class FilesViewModel extends ViewModel {
private static MutableLiveData<List<Files>> filesList;
private static MutableLiveData<List<Files>> filesList2;
public LiveData<List<Files>> getFilesList(String instanceUrl, String token, String owner, String repo, String ref, Context ctx) {
public LiveData<List<Files>> getFilesList(String instanceUrl, String token, String owner, String repo, String ref, Context ctx, ProgressBar progressBar, TextView noDataFiles) {
filesList = new MutableLiveData<>();
loadFilesList(instanceUrl, token, owner, repo, ref, ctx);
loadFilesList(instanceUrl, token, owner, repo, ref, ctx, progressBar, noDataFiles);
return filesList;
}
private static void loadFilesList(String instanceUrl, String token, String owner, String repo, String ref, final Context ctx) {
private static void loadFilesList(String instanceUrl, String token, String owner, String repo, String ref, final Context ctx, ProgressBar progressBar, TextView noDataFiles) {
Call<List<Files>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
@ -45,37 +47,47 @@ public class FilesViewModel extends ViewModel {
@Override
public void onResponse(@NonNull Call<List<Files>> call, @NonNull Response<List<Files>> response) {
if (response.isSuccessful()) {
if (response.code() == 200) {
assert response.body() != null;
Collections.sort(response.body(), (byType1, byType2) -> byType1.getType().compareTo(byType2.getType()));
filesList.postValue(response.body());
} else {
if(response.body().size() > 0) {
Toasty.warning(ctx, ctx.getString(R.string.noDataFilesTab));
Log.i("onResponse", String.valueOf(response.code()));
Collections.sort(response.body(), (byType1, byType2) -> byType1.getType().compareTo(byType2.getType()));
filesList.postValue(response.body());
}
else {
progressBar.setVisibility(View.GONE);
noDataFiles.setVisibility(View.VISIBLE);
}
}
else {
progressBar.setVisibility(View.GONE);
noDataFiles.setVisibility(View.VISIBLE);
}
}
@Override
public void onFailure(@NonNull Call<List<Files>> call, @NonNull Throwable t) {
Log.i("onFailure", t.toString());
Toasty.error(ctx, ctx.getString(R.string.errorOnLogin));
}
});
}
public LiveData<List<Files>> getFilesList2(String instanceUrl, String token, String owner, String repo, String filesDir, String ref, Context ctx) {
public LiveData<List<Files>> getFilesList2(String instanceUrl, String token, String owner, String repo, String filesDir, String ref, Context ctx, ProgressBar progressBar, TextView noDataFiles) {
filesList2 = new MutableLiveData<>();
loadFilesList2(instanceUrl, token, owner, repo, filesDir, ref, ctx);
loadFilesList2(instanceUrl, token, owner, repo, filesDir, ref, ctx, progressBar, noDataFiles);
return filesList2;
}
private static void loadFilesList2(String instanceUrl, String token, String owner, String repo, String filesDir, String ref, final Context ctx) {
private static void loadFilesList2(String instanceUrl, String token, String owner, String repo, String filesDir, String ref, final Context ctx, ProgressBar progressBar, TextView noDataFiles) {
Call<List<Files>> call = RetrofitClient
.getInstance(instanceUrl, ctx)
@ -87,23 +99,32 @@ public class FilesViewModel extends ViewModel {
@Override
public void onResponse(@NonNull Call<List<Files>> call, @NonNull Response<List<Files>> response) {
if (response.isSuccessful()) {
if (response.code() == 200) {
assert response.body() != null;
Collections.sort(response.body(), (byType1, byType2) -> byType1.getType().compareTo(byType2.getType()));
filesList2.postValue(response.body());
} else {
if(response.body().size() > 0) {
Toasty.warning(ctx, ctx.getString(R.string.noDataFilesTab));
Log.i("onResponse", String.valueOf(response.code()));
Collections.sort(response.body(), (byType1, byType2) -> byType1.getType().compareTo(byType2.getType()));
filesList2.postValue(response.body());
}
else {
progressBar.setVisibility(View.GONE);
noDataFiles.setVisibility(View.VISIBLE);
}
}
else {
progressBar.setVisibility(View.GONE);
noDataFiles.setVisibility(View.VISIBLE);
}
}
@Override
public void onFailure(@NonNull Call<List<Files>> call, @NonNull Throwable t) {
Log.i("onFailure", t.toString());
Toasty.error(ctx, ctx.getString(R.string.errorOnLogin));
}
});

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
tools:context=".activities.AddRemoveAssigneesActivity" />

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
tools:context=".activities.AddRemoveLabelsActivity" />

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/primaryBackgroundColor">
@ -55,155 +55,155 @@
android:padding="16dp"
android:orientation="vertical">
<TextView
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueTitleLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/newIssueTitle"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<EditText
android:id="@+id/newIssueTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:padding="10dp"
android:textSize="14sp"
tools:ignore="Autofill"
android:inputType="textCapSentences|text"
android:labelFor="@+id/newIssueTitle"
android:background="@drawable/shape_inputs"
android:textColor="?attr/inputTextColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
android:textColorHighlight="?attr/primaryTextColor" />
app:hintTextColor="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
app:counterEnabled="true"
app:counterMaxLength="255"
app:counterTextColor="?attr/inputTextColor"
android:hint="@string/newIssueTitle">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/newIssueDescriptionTitle"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:layout_marginTop="10dp"/>
<com.hendraanggrian.appcompat.widget.SocialAutoCompleteTextView
android:id="@+id/newIssueDescription"
android:layout_width="match_parent"
android:layout_height="240dp"
android:layout_marginTop="10dp"
android:padding="10dp"
android:completionThreshold="1"
android:background="@drawable/shape_inputs"
android:maxLines="10"
android:minLines="8"
tools:ignore="Autofill"
android:labelFor="@+id/newReplyToIssue"
android:scrollbars="vertical"
android:gravity="top|start"
android:textSize="14sp"
android:inputType="textCapSentences|textMultiLine"
android:textColor="?attr/inputTextColor"
android:textColorHint="?attr/hintColor"
android:textColorHighlight="?attr/primaryTextColor" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/newIssueAssigneesListTitle"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:layout_marginTop="10dp"/>
<TextView
android:id="@+id/newIssueAssigneesList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:padding="10dp"
android:textSize="14sp"
tools:ignore="Autofill"
android:background="@drawable/shape_inputs"
android:textColor="?attr/inputTextColor"
android:textColorHint="?attr/hintColor"
android:inputType="none"
android:textColorHighlight="?attr/primaryTextColor"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/labelsIdHolder"
android:visibility="gone" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/newIssueMilestoneTitle"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:layout_marginTop="10dp"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_dropdown"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp" >
<Spinner
android:id="@+id/newIssueMilestoneSpinner"
android:layout_width="wrap_content"
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/newIssueTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dropdown"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingStart="5dp" />
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="16sp" />
</RelativeLayout>
</com.google.android.material.textfield.TextInputLayout>
<TextView
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueDescriptionLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/newIssueLabelsTitle"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:layout_marginTop="10dp"/>
<TextView
android:id="@+id/newIssueLabels"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:padding="10dp"
android:textSize="14sp"
tools:ignore="Autofill"
android:background="@drawable/shape_inputs"
android:textColor="?attr/inputTextColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
android:inputType="none"
android:textColorHighlight="?attr/primaryTextColor"/>
app:hintTextColor="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
android:hint="@string/newIssueDescriptionTitle">
<TextView
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/newIssueDescription"
android:layout_width="match_parent"
android:layout_height="140dp"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueAssigneesListLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/newIssueDueDateTitle"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:layout_marginTop="10dp" />
<TextView
android:id="@+id/newIssueDueDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:layout_marginTop="10dp"
android:padding="10dp"
android:textSize="14sp"
tools:ignore="Autofill"
android:background="@drawable/shape_inputs"
android:textColor="?attr/inputTextColor"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
android:textColorHighlight="?attr/primaryTextColor"/>
app:hintTextColor="?attr/hintColor"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:hint="@string/newIssueAssigneesListTitle">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/newIssueAssigneesList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:focusable="false"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueMilestoneSpinnerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
app:hintTextColor="?attr/hintColor"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:hint="@string/newIssueMilestoneTitle"
app:endIconTint="?attr/iconsColor"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu">
<AutoCompleteTextView
android:id="@+id/newIssueMilestoneSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:textColor="?attr/inputTextColor"
android:labelFor="@+id/newIssueMilestoneSpinner"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueLabelsLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
app:hintTextColor="?attr/hintColor"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:hint="@string/newIssueLabelsTitle">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/newIssueLabels"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:focusable="false"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/newIssueDueDateLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
app:hintTextColor="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
android:hint="@string/newIssueDueDateTitle">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/newIssueDueDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:maxLines="1"
android:focusable="false"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/createNewIssueButton"

View File

@ -81,22 +81,6 @@
</RelativeLayout>
<LinearLayout
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/info"
android:layout_width="28dp"
android:layout_height="28dp"
android:src="@drawable/ic_info"
android:layout_marginStart="120dp"
android:layout_marginTop="10dp"
android:contentDescription="@string/urlInfoTooltip" />
</LinearLayout>
<EditText
android:id="@+id/instance_url"
android:layout_width="match_parent"

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/layoutFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<CheckBox
android:id="@+id/assigneesSelection"
android:layout_width="match_parent"
android:layout_height="36dp"
android:checked="false"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<androidx.cardview.widget.CardView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginTop="8dp"
android:layout_marginStart="36dp"
android:layout_marginEnd="4dp"
app:cardElevation="0dp"
app:cardCornerRadius="4dp">
<ImageView
android:id="@+id/assigneesAvatar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/assigneesName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingStart="64dp"
android:paddingEnd="4dp"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
</RelativeLayout>

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/shape_custom_dialog"
android:orientation="vertical">
<com.google.android.material.progressindicator.ProgressIndicator
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Indeterminate"
app:indicatorColor="?attr/progressIndicatorColor" />
<LinearLayout
android:id="@+id/dialogFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:id="@+id/TitleFrame"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:textStyle="bold"
android:drawableStart="@drawable/ic_person_add"
android:drawablePadding="16dp"
android:text="@string/newIssueSelectAssigneesListTitle" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:id="@+id/dividerTitle"
android:background="?attr/dividerColor" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="100"
android:layout_margin="12dp"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/assigneesRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:id="@+id/divider"
android:background="?attr/dividerColor" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:orientation="vertical" >
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="60dp"
style="?android:attr/button"
android:layout_alignParentStart="true"
android:text="@string/close"
android:textColor="@color/colorWhite"
android:textSize="16sp" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/layoutFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -10,10 +10,37 @@
<CheckBox
android:id="@+id/labelSelection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="36dp"
android:checked="false"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<androidx.cardview.widget.CardView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginTop="8dp"
android:layout_marginStart="36dp"
android:layout_marginEnd="4dp"
app:cardElevation="0dp"
app:cardCornerRadius="4dp">
<ImageView
android:id="@+id/labelColor"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/generalImgContentText" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/labelText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingStart="64dp"
android:paddingEnd="4dp"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
</RelativeLayout>

View File

@ -1,116 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/select_entry"
android:textColor="?attr/primaryTextColor"
android:textSize="24sp" />
<androidx.appcompat.widget.SearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:iconifiedByDefault="true"
android:queryHint="Search" />
<LinearLayout
android:id="@+id/select_all_container"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@color/colorPrimary"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/select_all_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="?attr/primaryTextColor"
android:clickable="false" />
<TextView
android:textAllCaps="true"
android:id="@+id/select_all_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:textSize="18sp"
android:textColor="?attr/primaryTextColor"
android:text="@string/select_all"/>
</LinearLayout>
<View
android:layout_marginTop="10dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:visibility="gone"
android:background="?attr/primaryBackgroundColor"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<view
android:id="@+id/recycler_view"
class="org.mian.gitnex.helpers.RecyclerViewEmptySupport"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/list_empty1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/noDataFound"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/cancel"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:textColor="@color/darkGreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancelButton" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Button
android:id="@+id/done"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:textColor="@color/darkRed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/doneButton" />
</LinearLayout>
</LinearLayout>

View File

@ -36,19 +36,19 @@
android:background="?attr/primaryBackgroundColor"
android:scrollbars="vertical" />
<TextView
android:id="@+id/noDataFiles"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"
android:gravity="center"
android:text="@string/noDataFilesTab"
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:visibility="gone" />
</LinearLayout>
<TextView
android:id="@+id/noDataFiles"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"
android:gravity="center"
android:text="@string/noDataFilesTab"
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:visibility="gone" />
<com.google.android.material.progressindicator.ProgressIndicator
android:id="@+id/progress_bar"
android:layout_width="match_parent"

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="?attr/primaryBackgroundColor"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/dialog_item_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="?attr/primaryTextColor"
android:clickable="false" />
<TextView
android:id="@+id/dialog_item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp" />
</LinearLayout>

View File

@ -219,7 +219,7 @@
<string name="issueCreated">New issue created successfully</string>
<string name="issueCreatedError">Something went wrong, please try again</string>
<string name="issueCreatedNoMilestone">No milestone</string>
<string name="noAssigneesFound">No collaborators found</string>
<string name="noAssigneesFound">No assignees found</string>
<string name="noLabelsFound">No labels found</string>
<!-- settings -->

View File

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