Merge branch 'master' into 7-assign-team-to-repo
This commit is contained in:
commit
8312983ed3
@ -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)
|
||||||
|
@ -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'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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) {}
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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,47 +276,50 @@ 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();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else if(id == R.id.repoMenu) {
|
||||||
|
|
||||||
case R.id.repoMenu:
|
|
||||||
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
|
BottomSheetRepoFragment bottomSheet = new BottomSheetRepoFragment();
|
||||||
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
|
bottomSheet.show(getSupportFragmentManager(), "repoBottomSheet");
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else if(id == R.id.filter) {
|
||||||
|
|
||||||
case R.id.filter:
|
|
||||||
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
|
BottomSheetIssuesFilterFragment filterBottomSheet = new BottomSheetIssuesFilterFragment();
|
||||||
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
|
filterBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuBottomSheet");
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else if(id == R.id.filterPr) {
|
||||||
|
|
||||||
case R.id.filterPr:
|
|
||||||
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
|
BottomSheetPullRequestFilterFragment filterPrBottomSheet = new BottomSheetPullRequestFilterFragment();
|
||||||
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
|
filterPrBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuPrBottomSheet");
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else if(id == R.id.filterMilestone) {
|
||||||
|
|
||||||
case R.id.filterMilestone:
|
|
||||||
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
|
BottomSheetMilestonesFilterFragment filterMilestoneBottomSheet = new BottomSheetMilestonesFilterFragment();
|
||||||
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
|
filterMilestoneBottomSheet.show(getSupportFragmentManager(), "repoFilterMenuMilestoneBottomSheet");
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else if(id == R.id.switchBranches) {
|
||||||
|
|
||||||
case R.id.switchBranches:
|
|
||||||
chooseBranch();
|
chooseBranch();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else if(id == R.id.branchCommits) {
|
||||||
|
|
||||||
case R.id.branchCommits:
|
|
||||||
Intent intent = new Intent(ctx, CommitsActivity.class);
|
Intent intent = new Intent(ctx, CommitsActivity.class);
|
||||||
intent.putExtra("branchName", tinyDB.getString("repoBranch"));
|
intent.putExtra("branchName", tinyDB.getString("repoBranch"));
|
||||||
ctx.startActivity(intent);
|
ctx.startActivity(intent);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user