Repo settings (delete-edit) (#683)

better var names

remove migration

Merge branch 'repo-settings-delete-migrate-edit' of codeberg.org:gitnex/GitNex into repo-settings-delete-migrate-edit

delete repository

Merge branch 'master' into repo-settings-delete-migrate-edit

Can edit repo properties now

Add progress indicator, call for save

Pull repo info into dialog

Repo properties in custom dialog

settings activity with labels

Merge branch 'master' into repo-settings-delete-migrate-edit

Merge branch 'master' of codeberg.org:gitnex/GitNex into master

add bottom sheet entry

endline

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/683
This commit is contained in:
M M Arif 2020-09-13 06:54:05 +02:00
parent dbf5be25a5
commit 5e6c600e71
23 changed files with 1078 additions and 67 deletions

View File

@ -84,6 +84,7 @@
<activity android:name=".activities.SettingsDraftsActivity" />
<activity android:name=".activities.RepoForksActivity" />
<activity android:name=".activities.AddNewAccountActivity" />
<activity android:name=".activities.RepositorySettingsActivity" />
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>

View File

@ -144,5 +144,4 @@ public class AddCollaboratorToRepositoryActivity extends BaseActivity {
onClickListener = view -> finish();
}
}

View File

@ -402,6 +402,10 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
}
break;
case "repoSettings":
startActivity(new Intent(RepoDetailActivity.this, RepositorySettingsActivity.class));
break;
}
}

View File

@ -0,0 +1,317 @@
package org.mian.gitnex.activities;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import com.google.gson.JsonElement;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.databinding.ActivityRepositorySettingsBinding;
import org.mian.gitnex.databinding.CustomRepositoryDeleteDialogBinding;
import org.mian.gitnex.databinding.CustomRepositoryEditPropertiesDialogBinding;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.models.UserRepositories;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class RepositorySettingsActivity extends BaseActivity {
private ActivityRepositorySettingsBinding viewBinding;
private CustomRepositoryEditPropertiesDialogBinding propBinding;
private CustomRepositoryDeleteDialogBinding deleteRepoBinding;
private Dialog dialogProp;
private Dialog dialogDeleteRepository;
private View.OnClickListener onClickListener;
private Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private String instanceUrl;
private String loginUid;
private String instanceToken;
private String repositoryOwner;
private String repositoryName;
@Override
protected int getLayoutResourceId(){
return R.layout.activity_repository_settings;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityRepositorySettingsBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
instanceUrl = tinyDb.getString("instanceUrl");
loginUid = tinyDb.getString("loginUid");
String repoFullName = tinyDb.getString("repoFullName");
String[] parts = repoFullName.split("/");
repositoryOwner = parts[0];
repositoryName = parts[1];
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
ImageView closeActivity = findViewById(R.id.close);
initCloseListener();
closeActivity.setOnClickListener(onClickListener);
viewBinding.editProperties.setOnClickListener(editProperties -> {
showRepositoryProperties();
});
viewBinding.deleteRepository.setOnClickListener(editProperties -> {
showDeleteRepository();
});
}
private void showDeleteRepository() {
dialogDeleteRepository = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogDeleteRepository.getWindow() != null) {
dialogDeleteRepository.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
deleteRepoBinding = CustomRepositoryDeleteDialogBinding.inflate(LayoutInflater.from(ctx));
View view = deleteRepoBinding.getRoot();
dialogDeleteRepository.setContentView(view);
deleteRepoBinding.cancel.setOnClickListener(editProperties -> {
dialogDeleteRepository.dismiss();
});
deleteRepoBinding.delete.setOnClickListener(deleteRepo -> {
if(!repositoryName.equals(String.valueOf(deleteRepoBinding.repoNameForDeletion.getText()))) {
Toasty.error(ctx, getString(R.string.repoSettingsDeleteError));
}
else {
deleteRepository();
}
});
dialogDeleteRepository.show();
}
private void deleteRepository() {
Call<JsonElement> deleteCall = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.deleteRepository(instanceToken, repositoryOwner, repositoryName);
deleteCall.enqueue(new Callback<JsonElement>() {
@Override
public void onResponse(@NonNull Call<JsonElement> call, @NonNull retrofit2.Response<JsonElement> response) {
deleteRepoBinding.delete.setVisibility(View.GONE);
deleteRepoBinding.processingRequest.setVisibility(View.VISIBLE);
if (response.code() == 204) {
dialogDeleteRepository.dismiss();
Toasty.success(ctx, getString(R.string.repoDeletionSuccess));
finish();
RepositoriesApi.deleteRepository((int) tinyDb.getLong("repositoryId", 0));
Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent);
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<JsonElement> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
}
private void showRepositoryProperties() {
dialogProp = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
if (dialogProp.getWindow() != null) {
dialogProp.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
propBinding = CustomRepositoryEditPropertiesDialogBinding.inflate(LayoutInflater.from(ctx));
View view = propBinding.getRoot();
dialogProp.setContentView(view);
propBinding.cancel.setOnClickListener(editProperties -> {
dialogProp.dismiss();
});
Call<UserRepositories> call = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.getUserRepository(instanceToken, repositoryOwner, repositoryName);
call.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
UserRepositories repoInfo = response.body();
propBinding.progressBar.setVisibility(View.GONE);
propBinding.mainView.setVisibility(View.VISIBLE);
if (response.code() == 200) {
assert repoInfo != null;
propBinding.repoName.setText(repoInfo.getName());
propBinding.repoWebsite.setText(repoInfo.getWebsite());
propBinding.repoDescription.setText(repoInfo.getDescription());
propBinding.repoPrivate.setChecked(repoInfo.getPrivateFlag());
propBinding.repoAsTemplate.setChecked(repoInfo.isTemplate());
propBinding.repoEnableIssues.setChecked(repoInfo.getHas_issues());
propBinding.repoEnableIssues.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
propBinding.repoEnableTimer.setVisibility(View.VISIBLE);
}
else {
propBinding.repoEnableTimer.setVisibility(View.GONE);
}
});
if(repoInfo.getInternal_tracker() != null) {
propBinding.repoEnableTimer.setChecked(repoInfo.getInternal_tracker().isEnable_time_tracker());
}
else {
propBinding.repoEnableTimer.setVisibility(View.GONE);
}
propBinding.repoEnableWiki.setChecked(repoInfo.isHas_wiki());
propBinding.repoEnablePr.setChecked(repoInfo.isHas_pull_requests());
propBinding.repoEnableMerge.setChecked(repoInfo.isAllow_merge_commits());
propBinding.repoEnableRebase.setChecked(repoInfo.isAllow_rebase());
propBinding.repoEnableSquash.setChecked(repoInfo.isAllow_squash_merge());
propBinding.repoEnableForceMerge.setChecked(repoInfo.isAllow_rebase_explicit());
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
propBinding.save.setOnClickListener(saveProperties -> saveRepositoryProperties(String.valueOf(propBinding.repoName.getText()),
String.valueOf(propBinding.repoWebsite.getText()),
String.valueOf(propBinding.repoDescription.getText()),
propBinding.repoPrivate.isChecked(), propBinding.repoAsTemplate.isChecked(),
propBinding.repoEnableIssues.isChecked(), propBinding.repoEnableWiki.isChecked(),
propBinding.repoEnablePr.isChecked(), propBinding.repoEnableTimer.isChecked(),
propBinding.repoEnableMerge.isChecked(), propBinding.repoEnableRebase.isChecked(),
propBinding.repoEnableSquash.isChecked(), propBinding.repoEnableForceMerge.isChecked()));
dialogProp.show();
}
private void saveRepositoryProperties(String repoName, String repoWebsite, String repoDescription,
boolean repoPrivate, boolean repoAsTemplate, boolean repoEnableIssues, boolean repoEnableWiki,
boolean repoEnablePr, boolean repoEnableTimer, boolean repoEnableMerge, boolean repoEnableRebase,
boolean repoEnableSquash, boolean repoEnableForceMerge) {
UserRepositories.internalTimeTrackerObject repoPropsTimeTracker = new UserRepositories.internalTimeTrackerObject(repoEnableTimer);
UserRepositories repoProps;
if(!repoEnableIssues) {
repoProps = new UserRepositories(repoName, repoWebsite, repoDescription, repoPrivate, repoAsTemplate, repoEnableIssues, repoEnableWiki, repoEnablePr, repoEnableMerge,
repoEnableRebase, repoEnableSquash, repoEnableForceMerge);
}
else {
repoProps = new UserRepositories(repoName, repoWebsite, repoDescription, repoPrivate, repoAsTemplate, repoEnableIssues, repoEnableWiki, repoEnablePr, repoPropsTimeTracker, repoEnableMerge,
repoEnableRebase, repoEnableSquash, repoEnableForceMerge);
}
Call<UserRepositories> propsCall = RetrofitClient
.getInstance(instanceUrl, ctx)
.getApiInterface()
.updateRepositoryProperties(instanceToken, repositoryOwner, repositoryName, repoProps);
propsCall.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
propBinding.save.setVisibility(View.GONE);
propBinding.processingRequest.setVisibility(View.VISIBLE);
if (response.code() == 200) {
dialogProp.dismiss();
Toasty.success(ctx, getString(R.string.repoPropertiesSaveSuccess));
if(!repositoryName.equals(repoName)) {
finish();
RepositoriesApi.updateRepositoryOwnerAndName(repositoryOwner, repoName, (int) tinyDb.getLong("repositoryId", 0));
Intent intent = new Intent(RepositorySettingsActivity.this, MainActivity.class);
RepositorySettingsActivity.this.startActivity(intent);
}
}
else {
Toasty.error(ctx, getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Toasty.error(ctx, getString(R.string.genericServerResponseError));
}
});
}
private void initCloseListener() {
onClickListener = view -> finish();
}
}

View File

@ -286,7 +286,7 @@ public class ExploreRepositoriesAdapter extends RecyclerView.Adapter<ExploreRepo
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);

View File

@ -291,7 +291,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.repoFullName.setText(currentItem.getFullname());
holder.repoFullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
@ -344,7 +344,7 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
String filterPattern = constraint.toString().toLowerCase().trim();
for(UserRepositories item : reposListFull) {
if(item.getFullname().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
if(item.getFullName().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}

View File

@ -85,7 +85,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter<NotificationsAdap
.getString(R.string.hash) + url.substring(url.lastIndexOf("/") + 1) + "</font>";
holder.subject.setText(Html.fromHtml(subjectId + " " + notificationThread.getSubject().getTitle()));
holder.repository.setText(notificationThread.getRepository().getFullname());
holder.repository.setText(notificationThread.getRepository().getFullName());
if(notificationThread.isPinned()) {
holder.pinned.setVisibility(View.VISIBLE);
@ -120,7 +120,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter<NotificationsAdap
onNotificationClickedListener.onNotificationClicked(notificationThread);
String[] parts = notificationThread.getRepository().getFullname().split("/");
String[] parts = notificationThread.getRepository().getFullName().split("/");
final String repoOwner = parts[0];
final String repoName = parts[1];

View File

@ -175,7 +175,7 @@ public class RepoForksAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
repoDescription.setVisibility(View.VISIBLE);
repoDescription.setText(forksModel.getDescription());
}
fullName.setText(forksModel.getFullname());
fullName.setText(forksModel.getFullName());
if(forksModel.getPrivateFlag()) {
repoPrivatePublic.setImageResource(R.drawable.ic_lock);

View File

@ -292,7 +292,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
@ -344,7 +344,7 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
String filterPattern = constraint.toString().toLowerCase().trim();
for(UserRepositories item : reposListFull) {
if(item.getFullname().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
if(item.getFullName().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}

View File

@ -292,7 +292,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
@ -340,7 +340,7 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
String filterPattern = constraint.toString().toLowerCase().trim();
for (UserRepositories item : reposListFull) {
if (item.getFullname().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
if (item.getFullName().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}

View File

@ -295,7 +295,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
holder.repoDescription.setVisibility(View.VISIBLE);
holder.repoDescription.setText(currentItem.getDescription());
}
holder.fullName.setText(currentItem.getFullname());
holder.fullName.setText(currentItem.getFullName());
if(currentItem.getPrivateFlag()) {
holder.repoPrivatePublic.setImageResource(R.drawable.ic_lock);
holder.repoType.setText(R.string.strPrivate);
@ -342,7 +342,7 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
String filterPattern = constraint.toString().toLowerCase().trim();
for (UserRepositories item : reposListFull) {
if (item.getFullname().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
if (item.getFullName().toLowerCase().contains(filterPattern) || item.getDescription().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}

View File

@ -127,6 +127,11 @@ public class RepositoriesApi {
return repository;
}
public static void updateRepositoryOwnerAndName(String repositoryOwner, String repositoryName, int repositoryId) {
new Thread(() -> repositoriesDao.updateRepositoryOwnerAndName(repositoryOwner, repositoryName, repositoryId)).start();
}
public static void deleteRepositoriesByAccount(final int repoAccountId) {
new Thread(() -> repositoriesDao.deleteRepositoriesByAccount(repoAccountId)).start();

View File

@ -41,6 +41,8 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
TextView unWatchRepository = v.findViewById(R.id.unWatchRepository);
TextView shareRepository = v.findViewById(R.id.shareRepository);
TextView copyRepoUrl = v.findViewById(R.id.copyRepoUrl);
View repoSettingsDivider = v.findViewById(R.id.repoSettingsDivider);
TextView repoSettings = v.findViewById(R.id.repoSettings);
createLabel.setOnClickListener(v112 -> {
@ -49,6 +51,7 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
});
if(tinyDb.getBoolean("hasIssues")) {
createIssue.setVisibility(View.VISIBLE);
createIssue.setOnClickListener(v12 -> {
@ -57,6 +60,7 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
});
}
else {
createIssue.setVisibility(View.GONE);
}
@ -67,13 +71,24 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
});
if (tinyDb.getBoolean("isRepoAdmin")) {
repoSettings.setOnClickListener(repoSettingsView -> {
bmListener.onButtonClicked("repoSettings");
dismiss();
});
addCollaborator.setOnClickListener(v1 -> {
bmListener.onButtonClicked("addCollaborator");
dismiss();
});
} else {
}
else {
addCollaborator.setVisibility(View.GONE);
repoSettingsDivider.setVisibility(View.GONE);
repoSettings.setVisibility(View.GONE);
}
createRelease.setOnClickListener(v14 -> {

View File

@ -337,7 +337,7 @@ public class NotificationsFragment extends Fragment implements NotificationsAdap
tinyDB.putString("issueNumber", issueUrl.substring(issueUrl.lastIndexOf("/") + 1));
tinyDB.putString("issueType", notificationThread.getSubject().getType());
tinyDB.putString("repoFullName", notificationThread.getRepository().getFullname());
tinyDB.putString("repoFullName", notificationThread.getRepository().getFullName());
startActivity(intent);

View File

@ -16,7 +16,6 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import org.mian.gitnex.R;
@ -35,7 +34,6 @@ import org.mian.gitnex.models.UserRepositories;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Objects;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin;
@ -44,7 +42,6 @@ import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
import io.noties.markwon.ext.tables.TablePlugin;
import io.noties.markwon.ext.tasklist.TaskListPlugin;
import io.noties.markwon.html.HtmlPlugin;
import io.noties.markwon.image.AsyncDrawable;
import io.noties.markwon.image.DefaultMediaDecoder;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
@ -164,17 +161,9 @@ public class RepoInfoFragment extends Fragment {
toggleExpandViewMeta();
}
fileContentsFrameHeader.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
toggleExpandView();
}
});
fileContentsFrameHeader.setOnClickListener(v1 -> toggleExpandView());
repoMetaFrameHeader.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
toggleExpandViewMeta();
}
});
repoMetaFrameHeader.setOnClickListener(v12 -> toggleExpandViewMeta());
repoMetaStarsFrame.setOnClickListener(metaStars -> {
@ -404,46 +393,37 @@ public class RepoInfoFragment extends Fragment {
if (response.code() == 200) {
final Markwon markwon = Markwon.builder(Objects.requireNonNull(getContext()))
final Markwon markwon = Markwon.builder(requireContext())
.usePlugin(CorePlugin.create())
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
@Override
public void configureImages(@NonNull ImagesPlugin plugin) {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
.usePlugin(ImagesPlugin.create(plugin -> {
plugin.addSchemeHandler(new SchemeHandler() {
@NonNull
@Override
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
final int resourceId = getContext().getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
getContext().getPackageName());
final int resourceId = requireContext().getResources().getIdentifier(
raw.substring("drawable://".length()),
"drawable",
requireContext().getPackageName());
final Drawable drawable = getContext().getDrawable(resourceId);
final Drawable drawable = requireContext().getDrawable(resourceId);
assert drawable != null;
return ImageItem.withResult(drawable);
}
assert drawable != null;
return ImageItem.withResult(drawable);
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(new ImagesPlugin.PlaceholderProvider() {
@Nullable
@Override
public Drawable providePlaceholder(@NonNull AsyncDrawable drawable) {
return null;
}
});
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(getContext().getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(getContext().getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}
@NonNull
@Override
public Collection<String> supportedSchemes() {
return Collections.singleton("drawable");
}
});
plugin.placeholderProvider(drawable -> null);
plugin.addMediaDecoder(GifMediaDecoder.create(false));
plugin.addMediaDecoder(SvgMediaDecoder.create(requireContext().getResources()));
plugin.addMediaDecoder(SvgMediaDecoder.create());
plugin.defaultMediaDecoder(DefaultMediaDecoder.create(requireContext().getResources()));
plugin.defaultMediaDecoder(DefaultMediaDecoder.create());
}))
.usePlugin(new AbstractMarkwonPlugin() {
@Override
@ -454,8 +434,8 @@ public class RepoInfoFragment extends Fragment {
.linkColor(getResources().getColor(R.color.lightBlue));
}
})
.usePlugin(TablePlugin.create(getContext()))
.usePlugin(TaskListPlugin.create(getContext()))
.usePlugin(TablePlugin.create(requireContext()))
.usePlugin(TaskListPlugin.create(requireContext()))
.usePlugin(HtmlPlugin.create())
.usePlugin(StrikethroughPlugin.create())
.usePlugin(LinkifyPlugin.create())

View File

@ -127,6 +127,12 @@ public interface ApiInterface {
@GET("repos/{owner}/{repo}") // get repo information
Call<UserRepositories> getUserRepository(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@PATCH("repos/{owner}/{repo}") // patch/update repository properties
Call<UserRepositories> updateRepositoryProperties(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Body UserRepositories jsonStr);
@DELETE("repos/{owner}/{repo}") // delete repository
Call<JsonElement> deleteRepository(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
@GET("repos/{owner}/{repo}/issues") // get issues by repo
Call<List<Issues>> getIssues(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("limit") int limit, @Query("type") String requestType, @Query("state") String issueState);

View File

@ -32,12 +32,134 @@ public class UserRepositories {
private Boolean has_issues;
private String avatar_url;
private boolean archived;
private boolean allow_merge_commits;
private boolean allow_rebase;
private boolean allow_rebase_explicit;
private boolean allow_squash_merge;
private boolean has_pull_requests;
private boolean has_wiki;
private boolean ignore_whitespace_conflicts;
private boolean template;
private permissionsObject permissions;
private externalIssueTrackerObject external_tracker;
private externalWikiObject external_wiki;
private internalTimeTrackerObject internal_tracker;
public UserRepositories(String body) {
this.name = name;
}
private permissionsObject permissions;
public UserRepositories(String name, String website, String description,
boolean repoPrivate, boolean repoAsTemplate, boolean repoEnableIssues,
boolean repoEnableWiki, boolean repoEnablePr,
boolean repoEnableMerge, boolean repoEnableRebase, boolean repoEnableSquash, boolean repoEnableForceMerge) {
this.name = name;
this.website = website;
this.description = description;
this.privateFlag = repoPrivate;
this.template = repoAsTemplate;
this.has_issues = repoEnableIssues;
this.has_wiki = repoEnableWiki;
this.has_pull_requests = repoEnablePr;
this.allow_merge_commits = repoEnableMerge;
this.allow_rebase = repoEnableRebase;
this.allow_squash_merge = repoEnableSquash;
this.allow_rebase_explicit = repoEnableForceMerge;
}
public UserRepositories(String name, String website, String description,
boolean repoPrivate, boolean repoAsTemplate, boolean repoEnableIssues,
boolean repoEnableWiki, boolean repoEnablePr, internalTimeTrackerObject repoEnableTimer,
boolean repoEnableMerge, boolean repoEnableRebase, boolean repoEnableSquash, boolean repoEnableForceMerge) {
this.name = name;
this.website = website;
this.description = description;
this.privateFlag = repoPrivate;
this.template = repoAsTemplate;
this.has_issues = repoEnableIssues;
this.has_wiki = repoEnableWiki;
this.has_pull_requests = repoEnablePr;
this.internal_tracker = repoEnableTimer;
this.allow_merge_commits = repoEnableMerge;
this.allow_rebase = repoEnableRebase;
this.allow_squash_merge = repoEnableSquash;
this.allow_rebase_explicit = repoEnableForceMerge;
}
public static class internalTimeTrackerObject {
private boolean allow_only_contributors_to_track_time;
private boolean enable_issue_dependencies;
private boolean enable_time_tracker;
public internalTimeTrackerObject(boolean enable_time_tracker) {
this.enable_time_tracker = enable_time_tracker;
}
public boolean isAllow_only_contributors_to_track_time() {
return allow_only_contributors_to_track_time;
}
public boolean isEnable_issue_dependencies() {
return enable_issue_dependencies;
}
public boolean isEnable_time_tracker() {
return enable_time_tracker;
}
}
public static class externalWikiObject {
private String external_wiki_url;
public externalWikiObject(String external_wiki_url) {
this.external_wiki_url = external_wiki_url;
}
public String getExternal_wiki_url() {
return external_wiki_url;
}
}
public static class externalIssueTrackerObject {
private String external_tracker_format;
private String external_tracker_style;
private String external_tracker_url;
public externalIssueTrackerObject(String external_tracker_url) {
this.external_tracker_url = external_tracker_url;
}
public String getExternal_tracker_format() {
return external_tracker_format;
}
public String getExternal_tracker_style() {
return external_tracker_style;
}
public String getExternal_tracker_url() {
return external_tracker_url;
}
}
public static class permissionsObject {
@ -72,7 +194,7 @@ public class UserRepositories {
return name;
}
public String getFullname() {
public String getFullName() {
return full_name;
}
@ -192,4 +314,64 @@ public class UserRepositories {
return archived;
}
public String getFull_name() {
return full_name;
}
public boolean isAllow_merge_commits() {
return allow_merge_commits;
}
public boolean isAllow_rebase() {
return allow_rebase;
}
public boolean isAllow_rebase_explicit() {
return allow_rebase_explicit;
}
public boolean isAllow_squash_merge() {
return allow_squash_merge;
}
public boolean isHas_pull_requests() {
return has_pull_requests;
}
public boolean isHas_wiki() {
return has_wiki;
}
public boolean isIgnore_whitespace_conflicts() {
return ignore_whitespace_conflicts;
}
public boolean isTemplate() {
return template;
}
public externalIssueTrackerObject getExternal_tracker() {
return external_tracker;
}
public externalWikiObject getExternal_wiki() {
return external_wiki;
}
public internalTimeTrackerObject getInternal_tracker() {
return internal_tracker;
}
}

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/iconsColor"
android:pathData="M4.75,0A2.75,2.75 0,0 0,2 2.75v16.5A2.75,2.75 0,0 0,4.75 22h11a0.75,0.75 0,0 0,0 -1.5h-11c-0.69,0 -1.25,-0.56 -1.25,-1.25V18A1.5,1.5 0,0 1,5 16.5h7.25a0.75,0.75 0,0 0,0 -1.5H5c-0.546,0 -1.059,0.146 -1.5,0.401V2.75c0,-0.69 0.56,-1.25 1.25,-1.25H18.5v7a0.75,0.75 0,0 0,1.5 0V0.75a0.75,0.75 0,0 0,-0.75 -0.75H4.75z"/>
<path
android:fillColor="?attr/iconsColor"
android:pathData="M20,13.903l2.202,2.359a0.75,0.75 0,0 0,1.096 -1.024l-3.5,-3.75a0.75,0.75 0,0 0,-1.096 0l-3.5,3.75a0.75,0.75 0,1 0,1.096 1.024l2.202,-2.36v9.348a0.75,0.75 0,0 0,1.5 0v-9.347z"/>
</vector>

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/primaryBackgroundColor">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/close_button_size"
android:layout_height="@dimen/close_button_size"
android:layout_marginRight="15dp"
android:layout_marginLeft="15dp"
android:gravity="center_vertical"
android:contentDescription="@string/close"
android:src="@drawable/ic_arrow_back" />
<TextView
android:id="@+id/toolbarTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/repoSettingsTitle"
android:textColor="?attr/primaryTextColor"
android:maxLines="1"
android:textSize="20sp" />
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="@+id/editProperties"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/repoSettingsEditProperties"
android:drawableStart="@drawable/ic_edit"
android:drawablePadding="32dp"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:padding="16dp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dividerColor" />
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content"
android:paddingBottom="16dp">
<TextView
android:id="@+id/deleteRepository"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/repoSettingsDelete"
android:drawableStart="@drawable/ic_delete"
android:drawablePadding="32dp"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:paddingTop="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp" />
<TextView
android:id="@+id/deleteRepositoryHint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/repoSettingsDeleteHint"
android:textColor="?attr/hintColor"
android:textSize="12sp"
android:paddingStart="72dp"
android:paddingEnd="16dp" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@ -189,6 +189,27 @@
android:textSize="16sp"
android:padding="12dp" />
<View
android:id="@+id/repoSettingsDivider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:layout_marginStart="64dp"
android:background="?attr/dividerColor" />
<TextView
android:id="@+id/repoSettings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:drawableStart="@drawable/ic_settings"
android:drawablePadding="24dp"
android:text="@string/navSettings"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:padding="12dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
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_delete"
android:drawablePadding="16dp"
android:text="@string/repoSettingsDelete"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:text="@string/repoSettingsDeleteDescription"
android:layout_marginBottom="16dp" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/repoNameForDeletionLayout"
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_marginBottom="8dp"
android:hint="@string/newRepoTintCopy">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/repoNameForDeletion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:id="@+id/divider"
android:background="?attr/dividerColor" />
<com.google.android.material.progressindicator.ProgressIndicator
android:id="@+id/processingRequest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Indeterminate"
app:indicatorColor="?attr/progressIndicatorColor" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:orientation="horizontal" >
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/button"
android:layout_alignParentStart="true"
android:text="@string/cancelButton"
android:textColor="@color/colorWhite"
android:textSize="16sp" />
<Button
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/button"
android:layout_alignParentEnd="true"
android:text="@string/menuDeleteText"
android:backgroundTint="@color/darkRed"
android:textColor="@color/colorWhite"
android:textSize="16sp"
tools:ignore="RelativeOverlap" />
</RelativeLayout>
</LinearLayout>

View File

@ -0,0 +1,231 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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" />
<androidx.core.widget.NestedScrollView
android:id="@+id/mainView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/repoNameLayout"
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_marginBottom="8dp"
android:hint="@string/newRepoTintCopy">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/repoName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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/repoWebsiteLayout"
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_marginBottom="8dp"
android:hint="@string/websiteText">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/repoWebsite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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/repoDescriptionLayout"
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:hint="@string/newRepoDescTintCopy">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/repoDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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.switchmaterial.SwitchMaterial
android:id="@+id/repoPrivate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/newRepoPrivateCopy" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoAsTemplate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesTemplate" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoEnableIssues"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesEnableIssues" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoEnableWiki"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesEnableWiki" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoEnablePr"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesEnablePr" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoEnableTimer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesEnableTimeTracker" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoEnableMerge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesEnableMergeCommits" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoEnableRebase"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesEnableRebase" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoEnableSquash"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesEnableSquash" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/repoEnableForceMerge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:checked="true"
android:textColor="?attr/primaryTextColor"
android:text="@string/repoPropertiesEnableForceMerge" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:id="@+id/divider"
android:background="?attr/dividerColor" />
<com.google.android.material.progressindicator.ProgressIndicator
android:id="@+id/processingRequest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Indeterminate"
app:indicatorColor="?attr/progressIndicatorColor" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:orientation="horizontal" >
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/button"
android:layout_alignParentStart="true"
android:text="@string/cancelButton"
android:textColor="@color/colorWhite"
android:textSize="16sp" />
<Button
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/button"
android:layout_alignParentEnd="true"
android:text="@string/saveButton"
android:textColor="@color/colorWhite"
android:textSize="16sp"
tools:ignore="RelativeOverlap" />
</RelativeLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@ -661,4 +661,24 @@
<string name="isRead">Read</string>
<string name="isUnread">Unread</string>
<string name="repoSettingsTitle">Repository Settings</string>
<string name="repoSettingsEditProperties">Edit Properties</string>
<string name="repoSettingsDelete">Delete Repository</string>
<string name="repoSettingsDeleteHint">Be careful, this operation CANNOT be undone!</string>
<string name="repoPropertiesTemplate">Set as Template</string>
<string name="repoPropertiesEnableIssues">Enable Issues</string>
<string name="repoPropertiesExternalIssuesUrl">External Issue Tracker Url</string>
<string name="repoPropertiesEnableWiki">Enable Wiki</string>
<string name="repoPropertiesExternalWikiUrl">External Wiki Url</string>
<string name="repoPropertiesEnablePr">Enable Pull Requests</string>
<string name="repoPropertiesEnableTimeTracker">Enable Time Tracker</string>
<string name="repoPropertiesEnableMergeCommits">Enable Merge Commits</string>
<string name="repoPropertiesEnableRebase">Enable Rebase</string>
<string name="repoPropertiesEnableSquash">Enable Squash and Merge</string>
<string name="repoPropertiesEnableForceMerge">Enable Rebase with Merge Commits (&#8212;&#8212;no-ff)</string>
<string name="repoPropertiesSaveSuccess">Repository properties updated successfully</string>
<string name="repoSettingsDeleteDescription">Things to know before deletion:\n\n- This operation CANNOT be undone.\n- This operation will permanently delete the repository including code, issues, comments, wiki data and collaborator settings.\n\nEnter the repository name as confirmation</string>
<string name="repoSettingsDeleteError">Repository name does not match</string>
<string name="repoDeletionSuccess">Repository deleted successfully</string>
</resources>