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

This commit is contained in:
opyale 2021-04-10 20:37:56 +02:00
commit 8312983ed3
17 changed files with 230 additions and 115 deletions

View File

@ -88,6 +88,7 @@ Thanks to all the open source libraries, contributors and donators.
- [ge0rg/MemorizingTrustManager](https://github.com/ge0rg/MemorizingTrustManager) - [ge0rg/MemorizingTrustManager](https://github.com/ge0rg/MemorizingTrustManager)
- [mikaelhg/urlbuilder](https://github.com/mikaelhg/urlbuilder) - [mikaelhg/urlbuilder](https://github.com/mikaelhg/urlbuilder)
- [ACRA/acra](https://github.com/ACRA/acra) - [ACRA/acra](https://github.com/ACRA/acra)
- [chrisvest/stormpot](https://github.com/chrisvest/stormpot)
#### Icon sets #### Icon sets
- [feathericons/feather](https://github.com/feathericons/feather) - [feathericons/feather](https://github.com/feathericons/feather)

View File

@ -112,5 +112,6 @@ dependencies {
implementation "org.codeberg.gitnex:tea4j:1.0.5" implementation "org.codeberg.gitnex:tea4j:1.0.5"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
implementation 'androidx.biometric:biometric:1.1.0' implementation 'androidx.biometric:biometric:1.1.0'
implementation 'com.github.chrisvest:stormpot:2.4.1'
} }

View File

@ -106,23 +106,23 @@ public class FileDiffActivity extends BaseActivity {
break; break;
case 401: case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx, runOnUiThread(() -> AlertDialogs.authorizationTokenRevokedDialog(ctx,
getString(R.string.alertDialogTokenRevokedTitle), getString(R.string.alertDialogTokenRevokedTitle),
getString(R.string.alertDialogTokenRevokedMessage), getString(R.string.alertDialogTokenRevokedMessage),
getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); getString(R.string.alertDialogTokenRevokedCopyPositiveButton)));
break; break;
case 403: case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); runOnUiThread(() -> Toasty.error(ctx, ctx.getString(R.string.authorizeError)));
break; break;
case 404: case 404:
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); runOnUiThread(() -> Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)));
break; break;
default: default:
Toasty.error(ctx, getString(R.string.labelGeneralError)); runOnUiThread(() -> Toasty.error(ctx, getString(R.string.labelGeneralError)));
} }
} catch(IOException ignored) {} } catch(IOException ignored) {}

View File

@ -240,23 +240,23 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
switch(response.code()) { switch(response.code()) {
case 401: case 401:
AlertDialogs.authorizationTokenRevokedDialog(ctx, runOnUiThread(() -> AlertDialogs.authorizationTokenRevokedDialog(ctx,
getResources().getString(R.string.alertDialogTokenRevokedTitle), getResources().getString(R.string.alertDialogTokenRevokedTitle),
getResources().getString(R.string.alertDialogTokenRevokedMessage), getResources().getString(R.string.alertDialogTokenRevokedMessage),
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton), getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)); getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton)));
break; break;
case 403: case 403:
Toasty.error(ctx, ctx.getString(R.string.authorizeError)); runOnUiThread(() -> Toasty.error(ctx, ctx.getString(R.string.authorizeError)));
break; break;
case 404: case 404:
Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)); runOnUiThread(() -> Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)));
break; break;
default: default:
Toasty.error(ctx, getString(R.string.labelGeneralError)); runOnUiThread(() -> Toasty.error(ctx, getString(R.string.labelGeneralError)));
} }
} }
@ -305,7 +305,7 @@ public class FileViewActivity extends BaseActivity implements BottomSheetFileVie
if(!tinyDB.getBoolean("enableMarkdownInFileView")) { if(!tinyDB.getBoolean("enableMarkdownInFileView")) {
new Markdown(ctx, EmojiParser.parseToUnicode(binding.contents.getContent()), binding.markdown); Markdown.render(ctx, EmojiParser.parseToUnicode(binding.contents.getContent()), binding.markdown);
binding.contents.setVisibility(View.GONE); binding.contents.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.VISIBLE); binding.markdownFrame.setVisibility(View.VISIBLE);

View File

@ -582,7 +582,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + EmojiParser.parseToUnicode(singleIssue.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY)); viewBinding.issueTitle.setText(HtmlCompat.fromHtml(issueNumber_ + " " + EmojiParser.parseToUnicode(singleIssue.getTitle()), HtmlCompat.FROM_HTML_MODE_LEGACY));
String cleanIssueDescription = singleIssue.getBody().trim(); String cleanIssueDescription = singleIssue.getBody().trim();
new Markdown(ctx, EmojiParser.parseToUnicode(cleanIssueDescription), viewBinding.issueDescription); Markdown.render(ctx, EmojiParser.parseToUnicode(cleanIssueDescription), viewBinding.issueDescription);
RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams) viewBinding.issueDescription.getLayoutParams(); RelativeLayout.LayoutParams paramsDesc = (RelativeLayout.LayoutParams) viewBinding.issueDescription.getLayoutParams();

View File

@ -17,6 +17,7 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -93,6 +94,14 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
Toolbar toolbar = findViewById(R.id.toolbar); Toolbar toolbar = findViewById(R.id.toolbar);
TextView toolbarTitle = findViewById(R.id.toolbar_title); TextView toolbarTitle = findViewById(R.id.toolbar_title);
ImageView repoTypeToolbar = findViewById(R.id.repoTypeToolbar);
if(tinyDB.getString("repoType").equalsIgnoreCase("private")) {
repoTypeToolbar.setVisibility(View.VISIBLE);
}
else {
repoTypeToolbar.setVisibility(View.GONE);
}
toolbarTitle.setText(repositoryName); toolbarTitle.setText(repositoryName);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
@ -267,46 +276,49 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
int id = item.getItemId(); int id = item.getItemId();
switch(id) { if(id == android.R.id.home) {
case android.R.id.home:
finish();
return true;
case R.id.repoMenu:
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true;
case R.id.filter:
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
return true;
case R.id.filterPr:
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
return true;
case R.id.filterMilestone:
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
return true;
case R.id.switchBranches:
chooseBranch();
return true;
case R.id.branchCommits:
Intent intent = new Intent(ctx, CommitsActivity.class);
intent.putExtra("branchName", tinyDB.getString("repoBranch"));
ctx.startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
finish();
return true;
} }
else if(id == R.id.repoMenu) {
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
return true;
}
else if(id == R.id.filter) {
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
return true;
}
else if(id == R.id.filterPr) {
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
return true;
}
else if(id == R.id.filterMilestone) {
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
return true;
}
else if(id == R.id.switchBranches) {
chooseBranch();
return true;
}
else if(id == R.id.branchCommits) {
Intent intent = new Intent(ctx, CommitsActivity.class);
intent.putExtra("branchName", tinyDB.getString("repoBranch"));
ctx.startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
} }

View File

@ -127,7 +127,7 @@ public class DraftsAdapter extends RecyclerView.Adapter<DraftsAdapter.DraftsView
holder.repoInfo.setText(headTitle); holder.repoInfo.setText(headTitle);
holder.draftWithRepository = currentItem; holder.draftWithRepository = currentItem;
new Markdown(mCtx, currentItem.getDraftText(), holder.draftText); Markdown.render(mCtx, currentItem.getDraftText(), holder.draftText);
if(!currentItem.getCommentId().equalsIgnoreCase("new")) { if(!currentItem.getCommentId().equalsIgnoreCase("new")) {
holder.editCommentStatus.setVisibility(View.VISIBLE); holder.editCommentStatus.setVisibility(View.VISIBLE);

View File

@ -332,7 +332,7 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
.centerCrop() .centerCrop()
.into(holder.avatar); .into(holder.avatar);
new Markdown(ctx, EmojiParser.parseToUnicode(issueComment.getBody()), holder.comment); Markdown.render(ctx, EmojiParser.parseToUnicode(issueComment.getBody()), holder.comment);
StringBuilder informationBuilder = null; StringBuilder informationBuilder = null;
if(issueComment.getCreated_at() != null) { if(issueComment.getCreated_at() != null) {
@ -349,9 +349,7 @@ public class IssueCommentsAdapter extends RecyclerView.Adapter<IssueCommentsAdap
} }
if(!issueComment.getCreated_at().equals(issueComment.getUpdated_at())) { if(!issueComment.getCreated_at().equals(issueComment.getUpdated_at())) {
if(informationBuilder != null) { if(informationBuilder != null) {
informationBuilder.append(ctx.getString(R.string.colorfulBulletSpan)).append(ctx.getString(R.string.modifiedText)); informationBuilder.append(ctx.getString(R.string.colorfulBulletSpan)).append(ctx.getString(R.string.modifiedText));
} }
} }

View File

@ -165,11 +165,11 @@ public class MilestonesAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
milestoneId.setText(String.valueOf(dataModel.getId())); milestoneId.setText(String.valueOf(dataModel.getId()));
milestoneStatus.setText(dataModel.getState()); milestoneStatus.setText(dataModel.getState());
new Markdown(context, dataModel.getTitle(), msTitle); Markdown.render(context, dataModel.getTitle(), msTitle);
if(!dataModel.getDescription().equals("")) { if(!dataModel.getDescription().equals("")) {
new Markdown(context, EmojiParser.parseToUnicode(dataModel.getDescription()), msDescription); Markdown.render(context, EmojiParser.parseToUnicode(dataModel.getDescription()), msDescription);
} }
else { else {

View File

@ -129,7 +129,7 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
} }
if(!currentItem.getBody().equals("")) { if(!currentItem.getBody().equals("")) {
new Markdown(mCtx, currentItem.getBody(), holder.releaseBodyContent); Markdown.render(mCtx, currentItem.getBody(), holder.releaseBodyContent);
} }
else { else {
holder.releaseBodyContent.setText(R.string.noReleaseBodyContent); holder.releaseBodyContent.setText(R.string.noReleaseBodyContent);

View File

@ -324,7 +324,7 @@ public class RepoInfoFragment extends Fragment {
switch(response.code()) { switch(response.code()) {
case 200: case 200:
new Markdown(ctx, response.body(), binding.repoFileContents); Markdown.render(ctx, response.body(), binding.repoFileContents);
break; break;
case 401: case 401:

View File

@ -9,8 +9,11 @@ import androidx.core.content.res.ResourcesCompat;
import org.mian.gitnex.R; import org.mian.gitnex.R;
import org.mian.gitnex.clients.PicassoService; import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.core.MainGrammarLocator; import org.mian.gitnex.core.MainGrammarLocator;
import java.util.Objects;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import io.noties.markwon.AbstractMarkwonPlugin; import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.Markwon; import io.noties.markwon.Markwon;
import io.noties.markwon.core.CorePlugin; import io.noties.markwon.core.CorePlugin;
@ -26,6 +29,13 @@ import io.noties.markwon.syntax.Prism4jThemeDarkula;
import io.noties.markwon.syntax.Prism4jThemeDefault; import io.noties.markwon.syntax.Prism4jThemeDefault;
import io.noties.markwon.syntax.SyntaxHighlightPlugin; import io.noties.markwon.syntax.SyntaxHighlightPlugin;
import io.noties.prism4j.Prism4j; import io.noties.prism4j.Prism4j;
import stormpot.Allocator;
import stormpot.BlazePool;
import stormpot.Config;
import stormpot.Pool;
import stormpot.Poolable;
import stormpot.Slot;
import stormpot.Timeout;
/** /**
* @author opyale * @author opyale
@ -33,26 +43,66 @@ import io.noties.prism4j.Prism4j;
public class Markdown { public class Markdown {
private static final ExecutorService executorService = Executors.newCachedThreadPool(); private static final int MAX_POOL_SIZE = 45;
private static final int MAX_THREAD_KEEP_ALIVE_SECONDS = 120;
private static final int MAX_CLAIM_TIMEOUT_SECONDS = 5;
private final Context context; private static final Timeout timeout = new Timeout(MAX_CLAIM_TIMEOUT_SECONDS, TimeUnit.SECONDS);
private final String markdown;
private final TextView textView;
public Markdown(@NonNull Context context, @NonNull String markdown, @NonNull TextView textView) { private static final ExecutorService executorService =
new ThreadPoolExecutor(MAX_POOL_SIZE / 2, MAX_POOL_SIZE, MAX_THREAD_KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, new SynchronousQueue<>());
this.context = context; private static final Pool<Renderer> rendererPool;
this.markdown = markdown;
this.textView = textView;
executorService.execute(new Renderer()); static {
Config<Renderer> config = new Config<>();
config.setBackgroundExpirationEnabled(true);
config.setPreciseLeakDetectionEnabled(true);
config.setSize(MAX_POOL_SIZE);
config.setAllocator(new Allocator<Renderer>() {
@Override
public Renderer allocate(Slot slot) throws Exception {
return new Renderer(slot);
}
@Override public void deallocate(Renderer poolable) throws Exception {}
});
rendererPool = new BlazePool<>(config);
} }
private class Renderer implements Runnable { public static void render(Context context, String markdown, TextView textView) {
@Override try {
public void run() { Renderer renderer = rendererPool.claim(timeout);
if(renderer != null) {
renderer.setParameters(context, markdown, textView);
executorService.execute(renderer);
}
} catch(InterruptedException ignored) {}
}
private static class Renderer implements Runnable, Poolable {
private final Slot slot;
private Markwon markwon;
private Context context;
private String markdown;
private TextView textView;
public Renderer(Slot slot) {
this.slot = slot;
}
private void setup() {
Prism4jTheme prism4jTheme = TinyDB.getInstance(context).getString("currentTheme").equals("dark") ? Prism4jTheme prism4jTheme = TinyDB.getInstance(context).getString("currentTheme").equals("dark") ?
Prism4jThemeDarkula.create() : Prism4jThemeDarkula.create() :
@ -72,16 +122,56 @@ public class Markdown {
@Override @Override
public void configureTheme(@NonNull MarkwonTheme.Builder builder) { public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
builder.codeBlockTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/sourcecodeproregular.ttf")); builder.codeBlockTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/sourcecodeproregular.ttf"));
builder.codeBlockMargin((int) (context.getResources().getDisplayMetrics().density * 10));
builder.blockMargin((int) (context.getResources().getDisplayMetrics().density * 10));
builder.codeTextSize((int) (context.getResources().getDisplayMetrics().scaledDensity * 13));
builder.codeTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/sourcecodeproregular.ttf")); builder.codeTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/sourcecodeproregular.ttf"));
builder.linkColor(ResourcesCompat.getColor(context.getResources(), R.color.lightBlue, null)); builder.linkColor(ResourcesCompat.getColor(context.getResources(), R.color.lightBlue, null));
} }
}); });
Markwon markwon = builder.build(); markwon = builder.build();
Spanned spanned = markwon.toMarkdown(markdown);
textView.post(() -> markwon.setParsedMarkdown(textView, spanned)); }
public void setParameters(Context context, String markdown, TextView textView) {
this.context = context;
this.markdown = markdown;
this.textView = textView;
}
@Override
public void run() {
Objects.requireNonNull(context);
Objects.requireNonNull(markdown);
Objects.requireNonNull(textView);
if(markwon == null) setup();
Spanned processedMarkdown = markwon.toMarkdown(markdown);
TextView localReference = textView;
localReference.post(() -> localReference.setText(processedMarkdown));
release();
}
@Override
public void release() {
context = null;
markdown = null;
textView = null;
slot.release(this);
}
public void expire() {
slot.expire(this);
} }
} }
} }

View File

@ -1,4 +1,4 @@
package org.mian.gitnex.helpers; package org.mian.gitnex.helpers.views;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
@ -16,6 +16,8 @@ import androidx.annotation.ColorInt;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.mian.gitnex.core.MainGrammarLocator; import org.mian.gitnex.core.MainGrammarLocator;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.TinyDB;
import io.noties.markwon.syntax.Prism4jSyntaxHighlight; import io.noties.markwon.syntax.Prism4jSyntaxHighlight;
import io.noties.markwon.syntax.Prism4jTheme; import io.noties.markwon.syntax.Prism4jTheme;
import io.noties.markwon.syntax.Prism4jThemeDarkula; import io.noties.markwon.syntax.Prism4jThemeDarkula;

View File

@ -99,7 +99,7 @@
</LinearLayout> </LinearLayout>
<org.mian.gitnex.helpers.SyntaxHighlightedArea <org.mian.gitnex.helpers.views.SyntaxHighlightedArea
android:id="@+id/contents" android:id="@+id/contents"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -23,6 +23,17 @@
android:layout_weight="1" android:layout_weight="1"
android:background="?attr/primaryBackgroundColor"> android:background="?attr/primaryBackgroundColor">
<ImageView
android:id="@+id/repoTypeToolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/generalImgContentText"
android:paddingStart="0dp"
android:paddingEnd="8dp"
android:src="@drawable/ic_lock"
android:visibility="gone"
tools:visibility="visible" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@ -37,8 +37,8 @@
<string name="pageTitleNewFile">Nuovo File</string> <string name="pageTitleNewFile">Nuovo File</string>
<string name="pageTitleExplore">Esplora</string> <string name="pageTitleExplore">Esplora</string>
<string name="pageTitleAdministration">Amministrazione Gitea</string> <string name="pageTitleAdministration">Amministrazione Gitea</string>
<string name="pageTitleUserAccounts">Manage Accounts</string> <string name="pageTitleUserAccounts">Gestione Account</string>
<string name="pageTitleNewPullRequest">New Pull Request</string> <string name="pageTitleNewPullRequest">Nuova Pull Request</string>
<!-- page titles --> <!-- page titles -->
<string name="repoName">Demo repo</string> <string name="repoName">Demo repo</string>
<string name="repoFullName">Repo con ORG</string> <string name="repoFullName">Repo con ORG</string>
@ -64,10 +64,10 @@
<string name="navigationDrawerOpen">Apri panello Navigazione</string> <string name="navigationDrawerOpen">Apri panello Navigazione</string>
<string name="navigationDrawerClose">Chiudi panello Navigazione</string> <string name="navigationDrawerClose">Chiudi panello Navigazione</string>
<string name="logo">Accedi a Gitea</string> <string name="logo">Accedi a Gitea</string>
<string name="protocol">Protocol</string> <string name="protocol">Protocollo</string>
<string name="urlInfoTooltip">1- Scegli il protocollo corretto(https or http). \n2- Enter Gitea url e.g: try.gitea.io. \n3- If you have enabled 2FA for your account, enter the code in the OTP Code field. \n4- For HTTP basic auth use USERNAME@DOMAIN.COM in the URL field.</string> <string name="urlInfoTooltip">1- Scegli il protocollo corretto(https or http). \n2- Enter Gitea url e.g: try.gitea.io. \n3- If you have enabled 2FA for your account, enter the code in the OTP Code field. \n4- For HTTP basic auth use USERNAME@DOMAIN.COM in the URL field.</string>
<string name="malformedUrl">Couldn\'t connect to host. Please check your URL or port for any errors</string> <string name="malformedUrl">Impossibile connettersi all\'host. Controlla l\'URL o la porta per eventuali errori</string>
<string name="protocolError">It is not recommended to use HTTP protocol unless you are testing on local network</string> <string name="protocolError">Non si consiglia di utilizzare il protocollo HTTP a meno che non si stia testando sulla rete locale</string>
<string name="malformedJson">Malformed JSON was received. Server response was not successful</string> <string name="malformedJson">Malformed JSON was received. Server response was not successful</string>
<string name="emptyFieldURL">Istanza <string name="emptyFieldURL">Istanza
URL è richiesto</string> URL è richiesto</string>
@ -107,8 +107,8 @@ URL è richiesto</string>
<string name="tabTextFiles">File</string> <string name="tabTextFiles">File</string>
<string name="tabTextMl">Milestones</string> <string name="tabTextMl">Milestones</string>
<string name="tabTextReleases">Rilasci</string> <string name="tabTextReleases">Rilasci</string>
<string name="tabTextBranches">Branches</string> <string name="tabTextBranches">Rami</string>
<string name="tabTextLabels">Labels</string> <string name="tabTextLabels">Etichette</string>
<string name="tabTextCollaborators">Collaboratori</string> <string name="tabTextCollaborators">Collaboratori</string>
<string name="tabPullRequests">Pull Requests</string> <string name="tabPullRequests">Pull Requests</string>
<string name="noDataIssueTab">Nessun problema trovato</string> <string name="noDataIssueTab">Nessun problema trovato</string>
@ -209,13 +209,13 @@ URL è richiesto</string>
<string name="draftsHintText">Bozze dei commenti</string> <string name="draftsHintText">Bozze dei commenti</string>
<string name="settingsEnableCommentsDeletionText">Abilita Eliminazione Bozze</string> <string name="settingsEnableCommentsDeletionText">Abilita Eliminazione Bozze</string>
<string name="settingsEnableCommentsDeletionHintText">Elimina la bozza del commento quando viene pubblicato</string> <string name="settingsEnableCommentsDeletionHintText">Elimina la bozza del commento quando viene pubblicato</string>
<string name="settingsGeneralHeader">General</string> <string name="settingsGeneralHeader">Generale</string>
<string name="generalHintText">Home screen, default link handler</string> <string name="generalHintText">Home screen, default link handler</string>
<string name="generalDeepLinkDefaultScreen">Default Link Handler</string> <string name="generalDeepLinkDefaultScreen">Default Link Handler</string>
<string name="generalDeepLinkDefaultScreenHintText">Choose what screen should be loaded if the app cannot handle external links. It will redirect you automatically.</string> <string name="generalDeepLinkDefaultScreenHintText">Choose what screen should be loaded if the app cannot handle external links. It will redirect you automatically.</string>
<string name="generalDeepLinkSelectedText">N/A</string> <string name="generalDeepLinkSelectedText">N/A</string>
<string name="linkSelectorDialogTitle">Select Default Link Handler Screen</string> <string name="linkSelectorDialogTitle">Select Default Link Handler Screen</string>
<string name="settingsBiometricHeader">Biometric Support</string> <string name="settingsBiometricHeader">Sblocco biometrico</string>
<!-- settings --> <!-- settings -->
<string name="noMoreData">Nessun altro dato disponibile</string> <string name="noMoreData">Nessun altro dato disponibile</string>
<string name="createLabel">Nuovo label</string> <string name="createLabel">Nuovo label</string>
@ -287,7 +287,7 @@ autorizzazione</string>
<string name="editCommentUpdatedText">Commento aggiornato</string> <string name="editCommentUpdatedText">Commento aggiornato</string>
<string name="issueCommentShare">Condividi Commento</string> <string name="issueCommentShare">Condividi Commento</string>
<string name="deleteCommentSuccess">Commento eliminato con successo</string> <string name="deleteCommentSuccess">Commento eliminato con successo</string>
<string name="copyCommentText">Copy Comment</string> <string name="copyCommentText">Copia commento</string>
<!-- issue comments --> <!-- issue comments -->
<!-- add collaborator --> <!-- add collaborator -->
<string name="addCollaboratorTitle">Aggiungi/Rimuovi collaboratore</string> <string name="addCollaboratorTitle">Aggiungi/Rimuovi collaboratore</string>
@ -305,7 +305,7 @@ autorizzazione</string>
<string name="profileEmailButton">Salva</string> <string name="profileEmailButton">Salva</string>
<string name="profileEmailTitle">Indirizzo Email</string> <string name="profileEmailTitle">Indirizzo Email</string>
<string name="emailAddedText">New email added successfully</string> <string name="emailAddedText">New email added successfully</string>
<string name="emailErrorEmpty">Email address is empty</string> <string name="emailErrorEmpty">L\'indirizzo email è vuoto</string>
<string name="emailErrorInvalid">Indirizzo email non valido</string> <string name="emailErrorInvalid">Indirizzo email non valido</string>
<string name="emailErrorInUse">Indirizzo email già in uso</string> <string name="emailErrorInUse">Indirizzo email già in uso</string>
<string name="emailTypeText">Primario</string> <string name="emailTypeText">Primario</string>
@ -331,8 +331,8 @@ autorizzazione</string>
<string name="userRoleAdmin">Amministratore</string> <string name="userRoleAdmin">Amministratore</string>
<string name="adminCron">Cron Tasks</string> <string name="adminCron">Cron Tasks</string>
<string name="adminCronScheduleHeader">Schedule</string> <string name="adminCronScheduleHeader">Schedule</string>
<string name="adminCronNextRunHeader">Next Run</string> <string name="adminCronNextRunHeader">Prossima esecuzione</string>
<string name="adminCronLastRunHeader">Last Run</string> <string name="adminCronLastRunHeader">Ultima esecuzione</string>
<string name="adminCronExecutionHeader">Executions</string> <string name="adminCronExecutionHeader">Executions</string>
<string name="adminCronTaskSuccessMsg">Task %1$s is initiated successfully</string> <string name="adminCronTaskSuccessMsg">Task %1$s is initiated successfully</string>
<!-- admin --> <!-- admin -->
@ -429,7 +429,7 @@ autorizzazione</string>
<string name="isOpen">Apri</string> <string name="isOpen">Apri</string>
<string name="isClosed">Chiuso</string> <string name="isClosed">Chiuso</string>
<string name="genericServerResponseError">Al momento non possiamo raggiungere il server, controlla lo stato del tuo server e riprova</string> <string name="genericServerResponseError">Al momento non possiamo raggiungere il server, controlla lo stato del tuo server e riprova</string>
<string name="genericCopyUrl">Copy URL</string> <string name="genericCopyUrl">Copia l\'URL</string>
<!-- generic copy --> <!-- generic copy -->
<string name="exploreTextBoxHint">Esplora i repository</string> <string name="exploreTextBoxHint">Esplora i repository</string>
<string name="starRepository">Repository star</string> <string name="starRepository">Repository star</string>
@ -479,9 +479,9 @@ autorizzazione</string>
<string name="waitLoadingDownloadFile">Attendere che il file venga caricato in memoria</string> <string name="waitLoadingDownloadFile">Attendere che il file venga caricato in memoria</string>
<string name="downloadFileSaved">File salvato con successo</string> <string name="downloadFileSaved">File salvato con successo</string>
<string name="excludeFilesInFileViewer">This file type/size is not supported in file viewer. You can download it from the menu.</string> <string name="excludeFilesInFileViewer">This file type/size is not supported in file viewer. You can download it from the menu.</string>
<string name="deleteFile">Delete This File</string> <string name="deleteFile">Elimina questo file</string>
<string name="editFile">Edit This File</string> <string name="editFile">Edit This File</string>
<string name="deleteFileText">Delete %1$s</string> <string name="deleteFileText">Elimina %1$s</string>
<string name="deleteFileMessage">File is set for deletion by branch %1$s</string> <string name="deleteFileMessage">File is set for deletion by branch %1$s</string>
<string name="editFileText">Edit %1$s</string> <string name="editFileText">Edit %1$s</string>
<string name="editFileMessage">File is modified by branch %1$s</string> <string name="editFileMessage">File is modified by branch %1$s</string>
@ -555,21 +555,21 @@ autorizzazione</string>
<string name="pinNotification">Fissa Notifica</string> <string name="pinNotification">Fissa Notifica</string>
<string name="markedNotificationsAsRead">Successfully marked all notifications as read</string> <string name="markedNotificationsAsRead">Successfully marked all notifications as read</string>
<string name="notificationsHintText">Polling delay, light, vibration</string> <string name="notificationsHintText">Polling delay, light, vibration</string>
<string name="enableNotificationsHeaderText">Enable Notifications</string> <string name="enableNotificationsHeaderText">Abilita le notifiche</string>
<string name="enableLightsHeaderText">Enable Light</string> <string name="enableLightsHeaderText">Enable Light</string>
<string name="enableVibrationHeaderText">Enable Vibration</string> <string name="enableVibrationHeaderText">Abilita la vibrazione</string>
<string name="chooseColorSelectorHeader">Choose Color</string> <string name="chooseColorSelectorHeader">Scegli il colore</string>
<string name="newMessages">New messages</string> <string name="newMessages">Nuovi messaggi</string>
<string name="youHaveGotNewNotifications">You\'ve got %d new notifications.</string> <string name="youHaveGotNewNotifications">You\'ve got %d new notifications.</string>
<string name="mainNotificationChannelName">Notifications</string> <string name="mainNotificationChannelName">Notifiche</string>
<string name="mainNotificationChannelDescription">This is the main notification channel of GitNex.</string> <string name="mainNotificationChannelDescription">This is the main notification channel of GitNex.</string>
<string name="isRead">Letto</string> <string name="isRead">Letto</string>
<string name="isUnread">Non letto</string> <string name="isUnread">Non letto</string>
<string name="repoSettingsTitle">Repository Settings</string> <string name="repoSettingsTitle">Impostazioni del repository</string>
<string name="repoSettingsEditProperties">Edit Properties</string> <string name="repoSettingsEditProperties">Modifica le proprietà</string>
<string name="repoSettingsDelete">Delete Repository</string> <string name="repoSettingsDelete">Elimina repository</string>
<string name="repoSettingsDeleteHint">Be careful, this operation CANNOT be undone!</string> <string name="repoSettingsDeleteHint">Be careful, this operation CANNOT be undone!</string>
<string name="repoPropertiesTemplate">Set as Template</string> <string name="repoPropertiesTemplate">Usa come modello</string>
<string name="repoPropertiesEnableIssues">Enable Issues</string> <string name="repoPropertiesEnableIssues">Enable Issues</string>
<string name="repoPropertiesExternalIssuesUrl">External Issue Tracker Url</string> <string name="repoPropertiesExternalIssuesUrl">External Issue Tracker Url</string>
<string name="repoPropertiesEnableWiki">Enable Wiki</string> <string name="repoPropertiesEnableWiki">Enable Wiki</string>
@ -613,8 +613,8 @@ autorizzazione</string>
<string name="codeBlockWhiteOnBlack">White on Black</string> <string name="codeBlockWhiteOnBlack">White on Black</string>
<string name="codeBlockGreyOnBlack">Grey on Black</string> <string name="codeBlockGreyOnBlack">Grey on Black</string>
<string name="codeBlockWhiteOnGrey">White on Grey</string> <string name="codeBlockWhiteOnGrey">White on Grey</string>
<string name="codeBlockDarkOnWhite">Dark on White</string> <string name="codeBlockDarkOnWhite">Nero su bianco</string>
<string name="biometricAuthTitle">Biometric Authentication</string> <string name="biometricAuthTitle">Autenticazione biometrica</string>
<string name="biometricAuthSubTitle">Unlock using your biometric credentials</string> <string name="biometricAuthSubTitle">Unlock using your biometric credentials</string>
<string name="biometricNotSupported">No biometric features available on this device</string> <string name="biometricNotSupported">No biometric features available on this device</string>
<string name="biometricNotAvailable">Biometric features are currently unavailable</string> <string name="biometricNotAvailable">Biometric features are currently unavailable</string>

View File

@ -476,7 +476,7 @@
<string name="downloadFile">下载此文件</string> <string name="downloadFile">下载此文件</string>
<string name="waitLoadingDownloadFile">请等待文件加载到内存</string> <string name="waitLoadingDownloadFile">请等待文件加载到内存</string>
<string name="downloadFileSaved">文件保存成功</string> <string name="downloadFileSaved">文件保存成功</string>
<string name="excludeFilesInFileViewer">This file type/size is not supported in file viewer. You can download it from the menu.</string> <string name="excludeFilesInFileViewer">文件查看器不支持此文件类型/大小。你可以从菜单下载。</string>
<string name="deleteFile">删除此文件</string> <string name="deleteFile">删除此文件</string>
<string name="editFile">编辑此文件</string> <string name="editFile">编辑此文件</string>
<string name="deleteFileText">删除 %1$s</string> <string name="deleteFileText">删除 %1$s</string>
@ -527,7 +527,7 @@
<string name="draftSaved">草稿已自动保存。</string> <string name="draftSaved">草稿已自动保存。</string>
<string name="appearanceHintText">主题、字体、徽章</string> <string name="appearanceHintText">主题、字体、徽章</string>
<string name="fileViewerHintText">PDF 模式,源代码主题</string> <string name="fileViewerHintText">PDF 模式,源代码主题</string>
<string name="securityHintText">Biometric authentication, SSL certificates, cache</string> <string name="securityHintText">生物特征认证、SSL证书、缓存</string>
<string name="languagesHintText">语言</string> <string name="languagesHintText">语言</string>
<string name="reportsHintText">崩溃报告</string> <string name="reportsHintText">崩溃报告</string>
<string name="rateAppHintText">如果你喜欢GitNex你可以给它点赞</string> <string name="rateAppHintText">如果你喜欢GitNex你可以给它点赞</string>
@ -559,8 +559,8 @@
<string name="chooseColorSelectorHeader">选择颜色</string> <string name="chooseColorSelectorHeader">选择颜色</string>
<string name="newMessages">新消息</string> <string name="newMessages">新消息</string>
<string name="youHaveGotNewNotifications">您有%d条新通知</string> <string name="youHaveGotNewNotifications">您有%d条新通知</string>
<string name="mainNotificationChannelName">Notifications</string> <string name="mainNotificationChannelName">通知</string>
<string name="mainNotificationChannelDescription">This is the main notification channel of GitNex.</string> <string name="mainNotificationChannelDescription">这是 GitNex 的主通知通道。</string>
<string name="isRead">已读</string> <string name="isRead">已读</string>
<string name="isUnread">未读</string> <string name="isUnread">未读</string>
<string name="repoSettingsTitle">存储库设置</string> <string name="repoSettingsTitle">存储库设置</string>
@ -619,12 +619,12 @@
<string name="enrollBiometric">从手机设置中注册生物识别</string> <string name="enrollBiometric">从手机设置中注册生物识别</string>
<string name="copyLoginIdToClipBoard">登录 ID \'%s\' 已复制到剪贴板</string> <string name="copyLoginIdToClipBoard">登录 ID \'%s\' 已复制到剪贴板</string>
<!-- file viewer activity --> <!-- file viewer activity -->
<string name="fileViewerNotificationTitleStarted">Download in progress</string> <string name="fileViewerNotificationTitleStarted">正在下载</string>
<string name="fileViewerNotificationDescriptionStarted">Downloading %s</string> <string name="fileViewerNotificationDescriptionStarted">正在下载 %s</string>
<string name="fileViewerNotificationTitleFinished">Download successful</string> <string name="fileViewerNotificationTitleFinished">下载成功</string>
<string name="fileViewerNotificationDescriptionFinished">Downloaded %s</string> <string name="fileViewerNotificationDescriptionFinished">已下载 %s</string>
<string name="fileViewerNotificationTitleFailed">Download failed</string> <string name="fileViewerNotificationTitleFailed">下载失败</string>
<string name="fileViewerNotificationDescriptionFailed">Couldn\'t download %s</string> <string name="fileViewerNotificationDescriptionFailed">无法下载 %s</string>
<string name="fileViewerNotificationChannelName">Download manager</string> <string name="fileViewerNotificationChannelName">下载管理器</string>
<string name="fileViewerNotificationChannelDescription">Indicates the progress of ongoing downloads</string> <string name="fileViewerNotificationChannelDescription">显示当前下载的进度</string>
</resources> </resources>