Create/list/edit/view/delete wiki (#1145)

Closes #17

- [x] create wiki
- [x] list wiki
- [x] view wiki
- [x] edit wiki
- [x] delete wiki

Co-authored-by: M M Arif <mmarif@swatian.com>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1145
Reviewed-by: qwerty287 <qwerty287@noreply.codeberg.org>
This commit is contained in:
M M Arif 2022-06-26 09:16:35 +02:00
parent f75fad2bea
commit 5bdbff4db6
87 changed files with 2568 additions and 252 deletions

View File

@ -39,7 +39,6 @@
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
<option name="BLANK_LINES_BEFORE_METHOD_BODY" value="1" />
<option name="BLANK_LINES_AROUND_FIELD_IN_INTERFACE" value="1" />
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
<option name="BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER" value="1" />

View File

@ -86,6 +86,7 @@ Thanks to all the open source libraries, contributors and donators.
- [mikaelhg/urlbuilder](https://github.com/mikaelhg/urlbuilder)
- [ACRA/acra](https://github.com/ACRA/acra)
- [chrisvest/stormpot](https://github.com/chrisvest/stormpot)
- [AmrDeveloper/CodeView](https://github.com/AmrDeveloper/CodeView)
#### Icon sets
- [lucide-icons/lucide](https://github.com/lucide-icons/lucide)

View File

@ -1,11 +1,11 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 31
compileSdkVersion 32
defaultConfig {
applicationId "org.mian.gitnex"
minSdkVersion 23
targetSdkVersion 31
targetSdkVersion 32
versionCode 435
versionName "4.4.0-dev"
multiDexEnabled true
@ -56,10 +56,10 @@ dependencies {
def acra = '5.8.4'
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
testImplementation 'junit:junit:4.13.2'
@ -95,7 +95,7 @@ dependencies {
implementation "io.noties.markwon:image-picasso:$markwon_version"
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
//noinspection GradleDependency
implementation 'commons-io:commons-io:2.11.0' // do not "upgrade" to 20030203.000550 - this was published over 15 years ago
implementation 'commons-io:commons-io:2.11.0'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation "com.github.chrisbanes:PhotoView:2.3.0"
implementation "ch.acra:acra-mail:$acra"
@ -114,4 +114,5 @@ dependencies {
implementation('org.codeberg.gitnex:tea4j-autodeploy:3111bc1b18') {
exclude module: 'org.apache.oltu.oauth2.common'
}
implementation 'io.github.amrdeveloper:codeview:1.3.5'
}

View File

@ -161,7 +161,14 @@
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.AdminCronTasksActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation" /> <!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.WikiActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation" />
<activity
android:windowSoftInputMode="adjustResize"
android:name=".activities.CodeEditorActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation" />
<meta-data
android:name="com.samsung.android.keepalive.density"
android:value="true" /> <!-- Version >= 3.0. DeX Dual Mode support -->

View File

@ -0,0 +1,122 @@
package org.mian.gitnex.activities;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import com.amrdeveloper.codeview.Code;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivityCodeEditorBinding;
import org.mian.gitnex.helpers.codeeditor.CustomCodeViewAdapter;
import org.mian.gitnex.helpers.codeeditor.LanguageManager;
import org.mian.gitnex.helpers.codeeditor.LanguageName;
import org.mian.gitnex.helpers.codeeditor.SourcePositionListener;
import org.mian.gitnex.helpers.codeeditor.ThemeName;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public class CodeEditorActivity extends BaseActivity {
private ActivityCodeEditorBinding binding;
private LanguageManager languageManager;
private final LanguageName currentLanguage = LanguageName.JAVA;
private final ThemeName currentTheme = ThemeName.FIVE_COLOR;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityCodeEditorBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.close.setOnClickListener(view -> finish());
configCodeView(currentLanguage);
configCodeViewPlugins();
}
private void configCodeView(LanguageName currentLanguage) {
binding.codeView.setTypeface(Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf"));
// Setup Line number feature
binding.codeView.setEnableLineNumber(true);
binding.codeView.setLineNumberTextColor(Color.GRAY);
binding.codeView.setLineNumberTextSize(44f);
// Setup Auto indenting feature
binding.codeView.setTabLength(4);
binding.codeView.setEnableAutoIndentation(true);
// Setup the language and theme with SyntaxManager helper class
languageManager = new LanguageManager(this, binding.codeView);
languageManager.applyTheme(currentLanguage, currentTheme);
// Setup auto pair complete
final Map<Character, Character> pairCompleteMap = new HashMap<>();
pairCompleteMap.put('{', '}');
pairCompleteMap.put('[', ']');
pairCompleteMap.put('(', ')');
pairCompleteMap.put('<', '>');
pairCompleteMap.put('"', '"');
pairCompleteMap.put('\'', '\'');
binding.codeView.setPairCompleteMap(pairCompleteMap);
binding.codeView.enablePairComplete(true);
binding.codeView.enablePairCompleteCenterCursor(true);
// Setup the auto complete and auto indenting for the current language
configLanguageAutoComplete();
configLanguageAutoIndentation();
}
private void configLanguageAutoComplete() {
boolean useModernAutoCompleteAdapter = true;
if (useModernAutoCompleteAdapter) {
List<Code> codeList = languageManager.getLanguageCodeList(currentLanguage);
CustomCodeViewAdapter adapter = new CustomCodeViewAdapter(this, codeList);
binding.codeView.setAdapter(adapter);
}
else {
String[] languageKeywords = languageManager.getLanguageKeywords(currentLanguage);
final int layoutId = R.layout.list_item_suggestion;
final int viewId = R.id.suggestItemTextView;
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, layoutId, viewId, languageKeywords);
binding.codeView.setAdapter(adapter);
}
}
private void configLanguageAutoIndentation() {
binding.codeView.setIndentationStarts(languageManager.getLanguageIndentationStarts(currentLanguage));
binding.codeView.setIndentationEnds(languageManager.getLanguageIndentationEnds(currentLanguage));
}
private void configCodeViewPlugins() {
configLanguageName();
binding.sourcePosition.setText(getString(R.string.sourcePosition, 0, 0));
configSourcePositionListener();
}
private void configLanguageName() {
binding.languageName.setText(currentLanguage.name().toLowerCase());
}
private void configSourcePositionListener() {
SourcePositionListener sourcePositionListener = new SourcePositionListener(binding.codeView);
sourcePositionListener.setOnPositionChanged((line, column) -> {
binding.sourcePosition.setText(getString(R.string.sourcePosition, line, column));
});
}
}

View File

@ -219,7 +219,7 @@ public class FileViewActivity extends BaseActivity implements BottomSheetListene
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
inflater.inflate(R.menu.files_view_menu, menu);
inflater.inflate(R.menu.markdown_switcher, menu);
if(!FilenameUtils.getExtension(file.getName())
.equalsIgnoreCase("md")) {

View File

@ -20,11 +20,12 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import org.gitnex.tea4j.v2.models.Branch;
import org.gitnex.tea4j.v2.models.Milestone;
import org.gitnex.tea4j.v2.models.Repository;
@ -44,6 +45,7 @@ import org.mian.gitnex.fragments.MilestonesFragment;
import org.mian.gitnex.fragments.PullRequestsFragment;
import org.mian.gitnex.fragments.ReleasesFragment;
import org.mian.gitnex.fragments.RepoInfoFragment;
import org.mian.gitnex.fragments.WikiFragment;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
@ -74,8 +76,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
private FragmentRefreshListener fragmentRefreshListenerFilterIssuesByMilestone;
private FragmentRefreshListener fragmentRefreshListenerReleases;
public ViewPager mViewPager;
private int tabsCount;
public ViewPager2 viewPager;
public RepositoryContext repository;
@ -344,6 +345,13 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
case "star":
repository.setStarred(true);
break;
case "createWiki":
Intent intent = new Intent(ctx, WikiActivity.class);
intent.putExtra("action", "add");
intent.putExtra(RepositoryContext.INTENT_EXTRA, ((RepoDetailActivity) ctx).repository);
ctx.startActivity(intent);
break;
}
}
@ -475,56 +483,46 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
});
}
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public class ViewPagerAdapter extends FragmentStateAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
public ViewPagerAdapter(@NonNull FragmentActivity fa) { super(fa); }
@NonNull
@Override
public Fragment getItem(int position) {
public Fragment createFragment(int position) {
Fragment fragment = null;
switch(position) {
case 0: // Repository details
return RepoInfoFragment.newInstance(repository);
case 1: // Files
return FilesFragment.newInstance(repository);
case 2: // Issues
fragment = IssuesFragment.newInstance(repository);
break;
case 3: // Pull requests
fragment = PullRequestsFragment.newInstance(repository);
break;
case 4: // Releases
return ReleasesFragment.newInstance(repository);
case 5: // Milestones
case 5: // Wiki
return WikiFragment.newInstance(repository);
case 6: // Milestones
fragment = MilestonesFragment.newInstance(repository);
break;
case 6: // Labels
case 7: // Labels
return LabelsFragment.newInstance(repository);
case 7: // Collaborators
case 8: // Collaborators
return CollaboratorsFragment.newInstance(repository);
}
assert fragment != null;
return fragment;
}
@Override
public int getCount() {
return tabsCount;
public int getItemCount() {
return 9;
}
}
@ -577,37 +575,37 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
}
TabLayout tabLayout = findViewById(R.id.tabs);
tabLayout.setVisibility(View.VISIBLE);
ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0);
tabsCount = viewGroup.getChildCount();
if(viewPager == null) {
for(int j = 0; j < tabsCount; j++) {
viewPager = findViewById(R.id.repositoryContainer);
viewPager.setOffscreenPageLimit(1);
ViewGroup vgTab = (ViewGroup) viewGroup.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
viewPager.setAdapter(new ViewPagerAdapter(this));
for(int i = 0; i < tabChildCount; i++) {
String[] tabTitles = {ctx.getResources().getString(R.string.tabTextInfo), ctx.getResources().getString(R.string.tabTextFiles), ctx.getResources().getString(R.string.pageTitleIssues), ctx.getResources().getString(R.string.tabPullRequests), ctx.getResources().getString(R.string.tabTextReleases), ctx.getResources().getString(R.string.wiki), ctx.getResources().getString(R.string.tabTextMl), ctx.getResources().getString(R.string.newIssueLabelsTitle), ctx.getResources().getString(R.string.tabTextCollaborators)};
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> tab.setText(tabTitles[position])).attach();
View tabViewChild = vgTab.getChildAt(i);
ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = viewGroup.getChildCount();
if(tabViewChild instanceof TextView) {
for(int j = 0; j < tabsCount; j++) {
((TextView) tabViewChild).setTypeface(myTypeface);
ViewGroup vgTab = (ViewGroup) viewGroup.getChildAt(j);
int tabChildCount = vgTab.getChildCount();
for(int i = 0; i < tabChildCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if(tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(myTypeface);
}
}
}
}
if(mViewPager == null) {
mViewPager = findViewById(R.id.container);
mViewPager.setVisibility(View.VISIBLE);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
}
if(tinyDB.getBoolean("enableCounterBadges", true)) {
@SuppressLint("InflateParams") View tabHeader2 = LayoutInflater.from(ctx).inflate(R.layout.badge_issue, null);
if(textViewBadgeIssue == null) {
@ -685,11 +683,11 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
switch(goToSectionType) {
case "branchesList":
mViewPager.setCurrentItem(1);
viewPager.setCurrentItem(1);
chooseBranch();
break;
case "branch":
mViewPager.setCurrentItem(1);
viewPager.setCurrentItem(1);
String selectedBranch = mainIntent.getStringExtra("selectedBranch");
repository.setBranchRef(selectedBranch);
if(getFragmentRefreshListenerFiles() != null) {
@ -697,7 +695,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
}
break;
case "file":
mViewPager.setCurrentItem(1);
viewPager.setCurrentItem(1);
String branch1 = mainIntent.getStringExtra("branch");
repository.setBranchRef(branch1);
if(getFragmentRefreshListenerFiles() != null) {
@ -708,7 +706,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
startActivity(intent);
break;
case "dir":
mViewPager.setCurrentItem(1);
viewPager.setCurrentItem(1);
String branch2 = mainIntent.getStringExtra("branch");
repository.setBranchRef(branch2);
if(getFragmentRefreshListenerFiles() != null) {
@ -716,7 +714,7 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
}
break;
case "commitsList":
mViewPager.setCurrentItem(1);
viewPager.setCurrentItem(1);
String branch = mainIntent.getStringExtra("branchName");
repository.setBranchRef(branch);
if(getFragmentRefreshListenerFiles() != null) {
@ -726,35 +724,35 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetListe
ctx.startActivity(intent1);
break;
case "issue":
mViewPager.setCurrentItem(2);
viewPager.setCurrentItem(2);
break;
case "issueNew":
mViewPager.setCurrentItem(2);
viewPager.setCurrentItem(2);
startActivity(repository.getIntent(ctx, CreateIssueActivity.class));
break;
case "pull":
mViewPager.setCurrentItem(3);
viewPager.setCurrentItem(3);
break;
case "pullNew":
mViewPager.setCurrentItem(3);
viewPager.setCurrentItem(3);
startActivity(repository.getIntent(ctx, CreatePullRequestActivity.class));
break;
case "releases":
mViewPager.setCurrentItem(4);
viewPager.setCurrentItem(4);
break;
case "newRelease":
mViewPager.setCurrentItem(4);
viewPager.setCurrentItem(4);
createReleaseLauncher.launch(repository.getIntent(ctx, CreateReleaseActivity.class));
break;
case "milestones":
mViewPager.setCurrentItem(5);
viewPager.setCurrentItem(5);
break;
case "milestonesNew":
mViewPager.setCurrentItem(5);
viewPager.setCurrentItem(5);
createMilestoneLauncher.launch(repository.getIntent(ctx, CreateMilestoneActivity.class));
break;
case "labels":
mViewPager.setCurrentItem(6);
viewPager.setCurrentItem(6);
break;
case "settings":
settingsLauncher.launch(repository.getIntent(ctx, RepositorySettingsActivity.class));

View File

@ -0,0 +1,404 @@
package org.mian.gitnex.activities;
import android.content.Intent;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import com.vdurmont.emoji.EmojiParser;
import org.gitnex.tea4j.v2.models.CreateWikiPageOptions;
import org.gitnex.tea4j.v2.models.WikiPage;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.ActivityWikiBinding;
import org.mian.gitnex.fragments.BottomSheetWikiFragment;
import org.mian.gitnex.fragments.WikiFragment;
import org.mian.gitnex.helpers.AlertDialogs;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Markdown;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import org.mian.gitnex.structs.BottomSheetListener;
import java.util.Objects;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* @author M M Arif
*/
public class WikiActivity extends BaseActivity implements BottomSheetListener {
private ActivityWikiBinding binding;
private String pageName;
private String action;
private RepositoryContext repository;
private boolean renderMd = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityWikiBinding.inflate(getLayoutInflater());
repository = RepositoryContext.fromIntent(getIntent());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
if(getIntent().getStringExtra("action") != null) {
action = getIntent().getStringExtra("action");
}
else {
action = "";
}
pageName = getIntent().getStringExtra("pageName");
binding.close.setOnClickListener(view -> finish());
binding.toolbarTitle.setMovementMethod(new ScrollingMovementMethod());
binding.toolbarTitle.setText(pageName);
if(action.equalsIgnoreCase("edit")) {
getWikiPageContents();
binding.renderWiki.setVisibility(View.GONE);
binding.wikiTitle.setText(pageName);
}
else if(action.equalsIgnoreCase("add")) {
binding.renderWiki.setVisibility(View.GONE);
binding.progressBar.setVisibility(View.GONE);
binding.toolbarTitle.setText(R.string.createWikiPage);
binding.createWiki.setVisibility(View.VISIBLE);
}
else {
getWikiPageContents();
binding.renderWiki.setVisibility(View.VISIBLE);
binding.createWiki.setVisibility(View.GONE);
}
}
private void processWiki() {
String wikiTitle = binding.wikiTitle.getText() != null ? binding.wikiTitle.getText().toString() : "";
String wikiContent = binding.wikiContent.getText() != null ? binding.wikiContent.getText().toString() : "";
if(wikiTitle.isEmpty() || wikiContent.isEmpty()) {
Toasty.error(ctx, getString(R.string.wikiPageNameAndContentError));
return;
}
if(action.equalsIgnoreCase("edit")) {
patchWiki(wikiTitle, wikiContent);
}
else if(action.equalsIgnoreCase("add")) {
addWiki(wikiTitle, wikiContent);
}
}
private void addWiki(String wikiTitle, String wikiContent) {
CreateWikiPageOptions createWikiPageOptions = new CreateWikiPageOptions();
createWikiPageOptions.setTitle(wikiTitle);
createWikiPageOptions.setContentBase64(AppUtil.encodeBase64(wikiContent));
Call<WikiPage> call = RetrofitClient
.getApiInterface(ctx)
.repoCreateWikiPage(repository.getOwner(), repository.getName(), createWikiPageOptions);
call.enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<WikiPage> call, @NonNull retrofit2.Response<WikiPage> response) {
if(response.isSuccessful()) {
if(response.code() == 201) {
Toasty.success(ctx, getString(R.string.wikiCreated));
WikiFragment.resumeWiki = true;
finish();
}
else {
switch(response.code()) {
case 401:
runOnUiThread(() -> AlertDialogs.authorizationTokenRevokedDialog(ctx));
break;
case 403:
runOnUiThread(() -> Toasty.error(ctx, ctx.getString(R.string.authorizeError)));
break;
case 404:
runOnUiThread(() -> Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)));
break;
default:
runOnUiThread(() -> Toasty.error(ctx, getString(R.string.genericError)));
}
}
}
}
@Override
public void onFailure(@NonNull Call<WikiPage> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
}
});
}
private void patchWiki(String wikiTitle, String wikiContent) {
CreateWikiPageOptions createWikiPageOptions = new CreateWikiPageOptions();
createWikiPageOptions.setTitle(wikiTitle);
createWikiPageOptions.setContentBase64(AppUtil.encodeBase64(wikiContent));
Call<WikiPage> call = RetrofitClient
.getApiInterface(ctx)
.repoEditWikiPage(repository.getOwner(), repository.getName(), pageName, createWikiPageOptions);
call.enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<WikiPage> call, @NonNull retrofit2.Response<WikiPage> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
Toasty.success(ctx, getString(R.string.wikiUpdated));
WikiFragment.resumeWiki = true;
finish();
}
else {
switch(response.code()) {
case 401:
runOnUiThread(() -> AlertDialogs.authorizationTokenRevokedDialog(ctx));
break;
case 403:
runOnUiThread(() -> Toasty.error(ctx, ctx.getString(R.string.authorizeError)));
break;
case 404:
runOnUiThread(() -> Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)));
break;
default:
runOnUiThread(() -> Toasty.error(ctx, getString(R.string.genericError)));
}
}
}
}
@Override
public void onFailure(@NonNull Call<WikiPage> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
}
});
}
private void getWikiPageContents() {
Call<WikiPage> call = RetrofitClient
.getApiInterface(ctx)
.repoGetWikiPage(repository.getOwner(), repository.getName(), pageName);
call.enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<WikiPage> call, @NonNull retrofit2.Response<WikiPage> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
WikiPage wikiPage = response.body();
runOnUiThread(() -> {
assert wikiPage != null;
String pageContents = AppUtil.decodeBase64(wikiPage.getContentBase64());
binding.contents.setContent(pageContents, "md");
if(renderMd) {
Markdown.render(ctx, EmojiParser.parseToUnicode(pageContents), binding.markdown, repository);
binding.markdownFrame.setVisibility(View.VISIBLE);
binding.contents.setVisibility(View.GONE);
}
else {
binding.markdownFrame.setVisibility(View.GONE);
binding.contents.setVisibility(View.VISIBLE);
}
if(action.equalsIgnoreCase("edit")) {
binding.wikiContent.setText(pageContents);
}
});
}
else {
switch(response.code()) {
case 401:
runOnUiThread(() -> AlertDialogs.authorizationTokenRevokedDialog(ctx));
break;
case 403:
runOnUiThread(() -> Toasty.error(ctx, ctx.getString(R.string.authorizeError)));
break;
case 404:
runOnUiThread(() -> Toasty.warning(ctx, ctx.getString(R.string.apiNotFound)));
break;
default:
runOnUiThread(() -> Toasty.error(ctx, getString(R.string.genericError)));
}
}
binding.progressBar.setVisibility(View.GONE);
}
}
@Override
public void onFailure(@NonNull Call<WikiPage> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
}
});
}
private void deleteWiki(final String owner, final String repo, final String pageName) {
new AlertDialog.Builder(ctx)
.setTitle(String.format(ctx.getString(R.string.deleteGenericTitle), pageName))
.setMessage(ctx.getString(R.string.deleteWikiPageMessage, pageName))
.setIcon(R.drawable.ic_delete)
.setPositiveButton(R.string.menuDeleteText, (dialog, whichButton) -> RetrofitClient
.getApiInterface(ctx).repoDeleteWikiPage(owner, repo, pageName).enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<Void> call, @NonNull Response<Void> response) {
if(response.isSuccessful()) {
Toasty.success(ctx, getString(R.string.wikiPageDeleted));
WikiFragment.resumeWiki = true;
finish();
}
else if(response.code() == 403) {
Toasty.error(ctx, ctx.getString(R.string.authorizeError));
}
else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}))
.setNeutralButton(R.string.cancelButton, null).show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.markdown_switcher, menu);
if(action.equalsIgnoreCase("edit") || action.equalsIgnoreCase("add")) {
inflater.inflate(R.menu.save, menu);
}
else {
if(repository.getPermissions().isPush()) {
inflater.inflate(R.menu.generic_nav_dotted_menu, menu);
}
}
return true;
}
@Override
public void onButtonClicked(String text) {
switch(text) {
case "editWiki":
Intent intent = new Intent(ctx, WikiActivity.class);
intent.putExtra("pageName", pageName);
intent.putExtra("action", "edit");
intent.putExtra(RepositoryContext.INTENT_EXTRA, repository);
ctx.startActivity(intent);
finish();
break;
case "delWiki":
deleteWiki(repository.getOwner(), repository.getName(), pageName);
break;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home) {
finish();
return true;
}
else if(id == R.id.genericMenu) {
BottomSheetWikiFragment bottomSheet = new BottomSheetWikiFragment();
bottomSheet.show(getSupportFragmentManager(), "wikiBottomSheet");
return true;
}
else if(id == R.id.save) {
processWiki();
return true;
}
else if(id == R.id.markdown) {
if(action.equalsIgnoreCase("edit") || action.equalsIgnoreCase("add")) {
if(renderMd) {
Markdown.render(ctx, EmojiParser.parseToUnicode(String.valueOf(
Objects.requireNonNull(binding.contentLayout.getEditText()).getText())), binding.markdownPreview, repository);
binding.markdownPreview.setVisibility(View.VISIBLE);
binding.contentLayout.setVisibility(View.GONE);
renderMd = false;
}
else {
binding.markdownPreview.setVisibility(View.GONE);
binding.contentLayout.setVisibility(View.VISIBLE);
renderMd = true;
}
}
else {
if(!renderMd) {
if(binding.markdown.getAdapter() == null) {
Markdown.render(ctx, EmojiParser.parseToUnicode(binding.contents.getContent()), binding.markdown, repository);
}
binding.contents.setVisibility(View.GONE);
binding.markdownFrame.setVisibility(View.VISIBLE);
renderMd = true;
}
else {
binding.markdownFrame.setVisibility(View.GONE);
binding.contents.setVisibility(View.VISIBLE);
renderMd = false;
}
}
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
}

View File

@ -21,13 +21,9 @@ import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import org.gitnex.tea4j.v2.models.Issue;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.BaseActivity;
import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.ProfileActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.ColorInverter;

View File

@ -17,9 +17,6 @@ import com.amulyakhare.textdrawable.util.ColorGenerator;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;

View File

@ -105,8 +105,7 @@ public class ReleasesAdapter extends RecyclerView.Adapter<ReleasesAdapter.Releas
optionsMenu.setOnClickListener(v -> {
final Context context = v.getContext();
@SuppressLint("InflateParams")
View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_release_in_list, null);
View view = LayoutInflater.from(context).inflate(R.layout.bottom_sheet_release_in_list, itemView.findViewById(android.R.id.content), false);
TextView deleteRelease = view.findViewById(R.id.deleteRelease);

View File

@ -17,9 +17,6 @@ import com.amulyakhare.textdrawable.util.ColorGenerator;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;

View File

@ -19,9 +19,6 @@ import com.amulyakhare.textdrawable.util.ColorGenerator;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;

View File

@ -0,0 +1,236 @@
package org.mian.gitnex.adapters;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.text.HtmlCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import org.gitnex.tea4j.v2.models.WikiPageMetaData;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.activities.WikiActivity;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentWikiBinding;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* @author M M Arif
*/
public class WikiListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context ctx;
private List<WikiPageMetaData> wikiList;
private OnLoadMoreListener loadMoreListener;
private boolean isLoading = false, isMoreDataAvailable = true;
private final FragmentWikiBinding fragmentWikiBinding;
private final String repoOwner;
private final String repoName;
public WikiListAdapter(List<WikiPageMetaData> wikiListMain, Context ctx, String repoOwner, String repoName, FragmentWikiBinding fragmentWikiBinding) {
this.ctx = ctx;
this.wikiList = wikiListMain;
this.repoOwner = repoOwner;
this.repoName = repoName;
this.fragmentWikiBinding = fragmentWikiBinding;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(ctx);
return new WikiListAdapter.WikisHolder(inflater.inflate(R.layout.list_wiki, parent, false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
((WikiListAdapter.WikisHolder) holder).bindData(wikiList.get(position));
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getItemCount() {
return wikiList.size();
}
class WikisHolder extends RecyclerView.ViewHolder {
private WikiPageMetaData wikiPageMeta;
private final ImageView avatar;
private final TextView pageName;
private final TextView wikiLastUpdatedBy;
private final ImageView wikiMenu;
WikisHolder(View itemView) {
super(itemView);
pageName = itemView.findViewById(R.id.page_name);
avatar = itemView.findViewById(R.id.image_avatar);
wikiLastUpdatedBy = itemView.findViewById(R.id.wiki_last_updated_by);
wikiMenu = itemView.findViewById(R.id.wiki_menu);
itemView.setOnClickListener(v -> {
Intent intent = new Intent(ctx, WikiActivity.class);
intent.putExtra("pageName", wikiPageMeta.getTitle());
intent.putExtra(RepositoryContext.INTENT_EXTRA, ((RepoDetailActivity) itemView.getContext()).repository);
ctx.startActivity(intent);
});
wikiMenu.setOnClickListener(v -> {
Context ctx = v.getContext();
View view = LayoutInflater.from(ctx).inflate(R.layout.bottom_sheet_wiki_in_list, itemView.findViewById(android.R.id.content), false);
TextView bottomSheetHeader = view.findViewById(R.id.bottom_sheet_header);
TextView editWiki = view.findViewById(R.id.edit_wiki);
TextView deleteWiki = view.findViewById(R.id.delete_wiki);
bottomSheetHeader.setText(wikiPageMeta.getTitle());
BottomSheetDialog dialog = new BottomSheetDialog(ctx);
dialog.setContentView(view);
dialog.show();
editWiki.setOnClickListener(v12 -> {
Intent intent = new Intent(ctx, WikiActivity.class);
intent.putExtra("pageName", wikiPageMeta.getTitle());
intent.putExtra("action", "edit");
intent.putExtra(RepositoryContext.INTENT_EXTRA, ((RepoDetailActivity) itemView.getContext()).repository);
ctx.startActivity(intent);
dialog.dismiss();
});
deleteWiki.setOnClickListener(v12 -> {
deleteWiki(repoOwner, repoName, wikiPageMeta.getTitle(), getAbsoluteAdapterPosition(), ctx);
dialog.dismiss();
});
});
}
@SuppressLint("SetTextI18n")
void bindData(WikiPageMetaData wikiPageMetaData) {
this.wikiPageMeta = wikiPageMetaData;
pageName.setText(wikiPageMetaData.getTitle());
wikiLastUpdatedBy.setText(
HtmlCompat.fromHtml(ctx.getResources().getString(R.string.wikiAuthor, wikiPageMetaData.getLastCommit().getAuthor().getName(),
TimeHelper.formatTime(TimeHelper.parseIso8601(wikiPageMetaData.getLastCommit().getAuthor().getDate()), ctx.getResources().getConfiguration().locale, "pretty",
ctx)), HtmlCompat.FROM_HTML_MODE_COMPACT));
this.wikiLastUpdatedBy.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(TimeHelper.parseIso8601(wikiPageMetaData.getLastCommit().getAuthor().getDate())), ctx));
ColorGenerator generator = ColorGenerator.Companion.getMATERIAL();
int color = generator.getColor(wikiPageMetaData.getTitle());
String firstCharacter = String.valueOf(wikiPageMetaData.getTitle().charAt(0));
TextDrawable drawable = TextDrawable.builder().beginConfig().useFont(Typeface.DEFAULT).fontSize(18).toUpperCase().width(28).height(28).endConfig().buildRoundRect(firstCharacter, color, 3);
avatar.setImageDrawable(drawable);
if(!((RepoDetailActivity) ctx).repository.getPermissions().isPush()) {
wikiMenu.setVisibility(View.GONE);
}
}
}
private void updateAdapter(int position) {
wikiList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, wikiList.size());
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
if(!isMoreDataAvailable) {
loadMoreListener.onLoadFinished();
}
}
@SuppressLint("NotifyDataSetChanged")
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
loadMoreListener.onLoadFinished();
}
public interface OnLoadMoreListener {
void onLoadMore();
void onLoadFinished();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public void updateList(List<WikiPageMetaData> list) {
wikiList = list;
notifyDataChanged();
}
private void deleteWiki(final String owner, final String repo, final String pageName, int position, final Context context) {
new AlertDialog.Builder(context)
.setTitle(String.format(context.getString(R.string.deleteGenericTitle), pageName))
.setMessage(context.getString(R.string.deleteWikiPageMessage, pageName))
.setIcon(R.drawable.ic_delete)
.setPositiveButton(R.string.menuDeleteText, (dialog, whichButton) -> RetrofitClient
.getApiInterface(context).repoDeleteWikiPage(owner, repo, pageName).enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<Void> call, @NonNull Response<Void> response) {
if(response.isSuccessful()) {
updateAdapter(position);
Toasty.success(context, context.getString(R.string.wikiPageDeleted));
if(getItemCount() == 0) {
fragmentWikiBinding.noData.setVisibility(View.VISIBLE);
}
}
else if(response.code() == 403) {
Toasty.error(context, context.getString(R.string.authorizeError));
}
else {
Toasty.error(context, context.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
Toasty.error(context, context.getString(R.string.genericError));
}
}))
.setNeutralButton(R.string.cancelButton, null).show();
}
}

View File

@ -18,8 +18,6 @@ import org.gitnex.tea4j.v2.models.Repository;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;

View File

@ -17,9 +17,6 @@ import com.amulyakhare.textdrawable.util.ColorGenerator;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.clients.PicassoService;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.ClickListener;
import org.mian.gitnex.helpers.RoundedTransformation;

View File

@ -9,7 +9,6 @@ import org.mian.gitnex.helpers.PicassoCache;
import org.mian.gitnex.helpers.ssl.MemorizingTrustManager;
import java.io.File;
import java.security.SecureRandom;
import java.util.Objects;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;

View File

@ -12,7 +12,7 @@ import org.mian.gitnex.databinding.BottomSheetAdminUsersBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetAdminUsersFragment extends BottomSheetDialogFragment {

View File

@ -14,7 +14,7 @@ import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetDraftsFragment extends BottomSheetDialogFragment {

View File

@ -13,7 +13,7 @@ import org.mian.gitnex.helpers.contexts.RepositoryContext;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetFileViewerFragment extends BottomSheetDialogFragment {

View File

@ -13,7 +13,7 @@ import org.mian.gitnex.databinding.BottomSheetIssuesFilterBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetIssuesFilterFragment extends BottomSheetDialogFragment {

View File

@ -13,7 +13,7 @@ import org.mian.gitnex.databinding.BottomSheetMilestonesFilterBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetMilestonesFilterFragment extends BottomSheetDialogFragment {

View File

@ -12,7 +12,7 @@ import org.mian.gitnex.activities.MyProfileEmailActivity;
import org.mian.gitnex.databinding.BottomSheetProfileBinding;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetMyProfileFragment extends BottomSheetDialogFragment {

View File

@ -11,7 +11,7 @@ import org.mian.gitnex.databinding.BottomSheetNotificationsFilterBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author opyale
* @author opyale
*/
public class BottomSheetNotificationsFilterFragment extends BottomSheetDialogFragment {

View File

@ -16,7 +16,7 @@ import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.SimpleCallback;
/**
* Author opyale
* @author opyale
*/
public class BottomSheetNotificationsFragment extends BottomSheetDialogFragment {

View File

@ -13,7 +13,7 @@ import org.mian.gitnex.databinding.BottomSheetOrganizationTeamsBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetOrganizationTeamsFragment extends BottomSheetDialogFragment {

View File

@ -12,7 +12,7 @@ import org.mian.gitnex.databinding.BottomSheetPullRequestFilterBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetPullRequestFilterFragment extends BottomSheetDialogFragment {

View File

@ -12,7 +12,7 @@ import org.mian.gitnex.databinding.BottomSheetReleasesTagsBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author opyale
* @author opyale
*/
public class BottomSheetReleasesTagsFragment extends BottomSheetDialogFragment {

View File

@ -29,8 +29,6 @@ import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.databinding.BottomSheetReplyLayoutBinding;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.TinyDB;

View File

@ -10,12 +10,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.actions.RepositoryActions;
import org.mian.gitnex.activities.BaseActivity;
import org.mian.gitnex.databinding.BottomSheetRepoBinding;
import org.mian.gitnex.helpers.contexts.AccountContext;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Author M M Arif
* @author M M Arif
*/
public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
@ -33,6 +35,8 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
BottomSheetRepoBinding bottomSheetRepoBinding = BottomSheetRepoBinding.inflate(inflater, container, false);
AccountContext account = ((BaseActivity) requireActivity()).getAccount();
TextView createLabel = bottomSheetRepoBinding.createLabel;
TextView createIssue = bottomSheetRepoBinding.createNewIssue;
TextView createMilestone = bottomSheetRepoBinding.createNewMilestone;
@ -48,6 +52,7 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
TextView copyRepoUrl = bottomSheetRepoBinding.copyRepoUrl;
TextView repoSettings = bottomSheetRepoBinding.repoSettings;
TextView createPullRequest = bottomSheetRepoBinding.createPullRequest;
TextView createWiki = bottomSheetRepoBinding.createWiki;
boolean canPush = repository.getPermissions().isPush();
if(!canPush) {
@ -57,6 +62,10 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
newFile.setVisibility(View.GONE);
}
if(!account.requiresVersion("1.16")) {
createWiki.setVisibility(View.GONE);
}
boolean archived = repository.getRepository().isArchived();
if(archived) {
createIssue.setVisibility(View.GONE);
@ -65,6 +74,7 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
createLabel.setVisibility(View.GONE);
createRelease.setVisibility(View.GONE);
newFile.setVisibility(View.GONE);
createWiki.setVisibility(View.GONE);
}
createLabel.setOnClickListener(v112 -> {
@ -120,11 +130,18 @@ public class BottomSheetRepoFragment extends BottomSheetDialogFragment {
bmListener.onButtonClicked("addCollaborator");
dismiss();
});
createWiki.setOnClickListener(v1 -> {
bmListener.onButtonClicked("createWiki");
dismiss();
});
}
else {
addCollaborator.setVisibility(View.GONE);
repoSettings.setVisibility(View.GONE);
createWiki.setVisibility(View.GONE);
}
createRelease.setOnClickListener(v14 -> {

View File

@ -12,7 +12,7 @@ import org.mian.gitnex.databinding.BottomSheetUserProfileBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* Template Author M M Arif
* @author M M Arif
* @author qwerty287
*/

View File

@ -0,0 +1,53 @@
package org.mian.gitnex.fragments;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import org.mian.gitnex.databinding.BottomSheetWikiInListBinding;
import org.mian.gitnex.structs.BottomSheetListener;
/**
* @author M M Arif
*/
public class BottomSheetWikiFragment extends BottomSheetDialogFragment {
private BottomSheetListener bmListener;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
BottomSheetWikiInListBinding bottomSheetWikiInListBinding = BottomSheetWikiInListBinding.inflate(inflater, container, false);
bottomSheetWikiInListBinding.editWiki.setOnClickListener(v1 -> {
bmListener.onButtonClicked("editWiki");
dismiss();
});
bottomSheetWikiInListBinding.deleteWiki.setOnClickListener(v12 -> {
bmListener.onButtonClicked("delWiki");
dismiss();
});
return bottomSheetWikiInListBinding.getRoot();
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
bmListener = (BottomSheetListener) context;
}
catch(ClassCastException e) {
throw new ClassCastException(context + " must implement BottomSheetListener");
}
}
}

View File

@ -16,7 +16,7 @@ import org.mian.gitnex.helpers.contexts.RepositoryContext;
import org.mian.gitnex.viewmodels.CollaboratorsViewModel;
/**
* Author M M Arif
* @author M M Arif
*/
public class CollaboratorsFragment extends Fragment {

View File

@ -28,9 +28,7 @@ import org.mian.gitnex.helpers.FileDiffView;
import org.mian.gitnex.helpers.ParseDiff;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TimeHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.Version;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import java.util.List;
import java.util.Objects;

View File

@ -104,7 +104,7 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
@Override
public void handleOnBackPressed() {
if(path.size() == 0 || ((RepoDetailActivity) requireActivity()).mViewPager.getCurrentItem() != 1) {
if(path.size() == 0 || ((RepoDetailActivity) requireActivity()).viewPager.getCurrentItem() != 1) {
requireActivity().finish();
return;
}

View File

@ -23,14 +23,10 @@ import org.mian.gitnex.activities.IssueDetailActivity;
import org.mian.gitnex.activities.RepoDetailActivity;
import org.mian.gitnex.adapters.NotificationsAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.BaseApi;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.databinding.FragmentNotificationsBinding;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.SimpleCallback;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.contexts.IssueContext;
import org.mian.gitnex.helpers.contexts.RepositoryContext;

View File

@ -93,7 +93,7 @@ public class RepoInfoFragment extends Fragment {
binding.repoMetaForksFrame.setOnClickListener(metaForks -> ctx.startActivity(repository.getIntent(ctx, RepoForksActivity.class)));
binding.repoMetaPullRequestsFrame.setOnClickListener(metaPR -> ((RepoDetailActivity) requireActivity()).mViewPager.setCurrentItem(3));
binding.repoMetaPullRequestsFrame.setOnClickListener(metaPR -> ((RepoDetailActivity) requireActivity()).viewPager.setCurrentItem(3));
return binding.getRoot();
}

View File

@ -0,0 +1,124 @@
package org.mian.gitnex.fragments;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.WikiListAdapter;
import org.mian.gitnex.databinding.FragmentWikiBinding;
import org.mian.gitnex.helpers.Constants;
import org.mian.gitnex.helpers.DividerItemDecorator;
import org.mian.gitnex.helpers.contexts.RepositoryContext;
import org.mian.gitnex.viewmodels.WikiViewModel;
/**
* @author M M Arif
*/
public class WikiFragment extends Fragment {
public static boolean resumeWiki = false;
private WikiViewModel wikiViewModel;
private FragmentWikiBinding fragmentWikiBinding;
private WikiListAdapter adapter;
private int page = 1;
private int resultLimit;
private RepositoryContext repository;
public static WikiFragment newInstance(RepositoryContext repository) {
WikiFragment fragment = new WikiFragment();
fragment.setArguments(repository.getBundle());
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
repository = RepositoryContext.fromBundle(requireArguments());
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
fragmentWikiBinding = FragmentWikiBinding.inflate(inflater, container, false);
setHasOptionsMenu(true);
wikiViewModel = new ViewModelProvider(this).get(WikiViewModel.class);
resultLimit = Constants.getCurrentResultLimit(getContext());
fragmentWikiBinding.recyclerView.setHasFixedSize(true);
fragmentWikiBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
RecyclerView.ItemDecoration dividerItemDecoration = new DividerItemDecorator(ContextCompat.getDrawable(requireContext(), R.drawable.shape_list_divider));
fragmentWikiBinding.recyclerView.addItemDecoration(dividerItemDecoration);
fragmentWikiBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
page = 1;
fragmentWikiBinding.pullToRefresh.setRefreshing(false);
fetchDataAsync(repository.getOwner(), repository.getName());
fragmentWikiBinding.progressBar.setVisibility(View.VISIBLE);
}, 50));
fetchDataAsync(repository.getOwner(), repository.getName());
return fragmentWikiBinding.getRoot();
};
@Override
public void onResume() {
super.onResume();
if(resumeWiki) {
page = 1;
fetchDataAsync(repository.getOwner(), repository.getName());
resumeWiki = false;
}
}
private void fetchDataAsync(String owner, String repo) {
wikiViewModel.getWiki(owner, repo, page, resultLimit, getContext(), fragmentWikiBinding).observe(getViewLifecycleOwner(), wikiListMain -> {
adapter = new WikiListAdapter(wikiListMain, getContext(), owner, repo, fragmentWikiBinding);
adapter.setLoadMoreListener(new WikiListAdapter.OnLoadMoreListener() {
@Override
public void onLoadMore() {
page += 1;
wikiViewModel.loadMoreWiki(repository.getOwner(), repository.getName(), page, resultLimit, getContext(), fragmentWikiBinding, adapter);
fragmentWikiBinding.progressBar.setVisibility(View.VISIBLE);
}
@Override
public void onLoadFinished() {
fragmentWikiBinding.progressBar.setVisibility(View.GONE);
}
});
if(adapter.getItemCount() > 0) {
fragmentWikiBinding.recyclerView.setAdapter(adapter);
fragmentWikiBinding.noData.setVisibility(View.GONE);
}
else {
adapter.notifyDataChanged();
fragmentWikiBinding.recyclerView.setAdapter(adapter);
fragmentWikiBinding.noData.setVisibility(View.VISIBLE);
}
fragmentWikiBinding.progressBar.setVisibility(View.GONE);
});
}
}

View File

@ -0,0 +1,50 @@
package org.mian.gitnex.helpers.codeeditor;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import com.amrdeveloper.codeview.Code;
import com.amrdeveloper.codeview.CodeViewAdapter;
import com.amrdeveloper.codeview.Snippet;
import org.mian.gitnex.R;
import java.util.List;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public class CustomCodeViewAdapter extends CodeViewAdapter {
private final LayoutInflater layoutInflater;
public CustomCodeViewAdapter(@NonNull Context context, @NonNull List<Code> codes) {
super(context, R.layout.list_items_autocomplete, 0, codes);
this.layoutInflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.list_items_autocomplete, parent, false);
}
ImageView codeType = convertView.findViewById(R.id.code_type);
TextView codeTitle = convertView.findViewById(R.id.code_title);
Code currentCode = (Code) getItem(position);
if (currentCode != null) {
codeTitle.setText(currentCode.getCodeTitle());
if (currentCode instanceof Snippet) {
codeType.setImageResource(R.drawable.ic_snippet);
} else {
codeType.setImageResource(R.drawable.ic_keyword);
}
}
return convertView;
}
}

View File

@ -0,0 +1,85 @@
package org.mian.gitnex.helpers.codeeditor;
import android.content.Context;
import com.amrdeveloper.codeview.Code;
import com.amrdeveloper.codeview.CodeView;
import org.mian.gitnex.helpers.codeeditor.languages.GoLanguage;
import org.mian.gitnex.helpers.codeeditor.languages.JavaLanguage;
import org.mian.gitnex.helpers.codeeditor.languages.PythonLanguage;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public class LanguageManager {
private final Context context;
private final CodeView codeView;
public LanguageManager(Context context, CodeView codeView) {
this.context = context;
this.codeView = codeView;
}
public void applyTheme(LanguageName language, ThemeName theme) {
if(theme == ThemeName.FIVE_COLOR) {
applyFiveColorsDarkTheme(language);
}
}
public String[] getLanguageKeywords(LanguageName language) {
switch (language) {
case JAVA: return JavaLanguage.getKeywords(context);
case PYTHON: return PythonLanguage.getKeywords(context);
case GO_LANG: return GoLanguage.getKeywords(context);
default: return new String[]{};
}
}
public List<Code> getLanguageCodeList(LanguageName language) {
switch (language) {
case JAVA: return JavaLanguage.getCodeList(context);
case PYTHON: return PythonLanguage.getCodeList(context);
case GO_LANG: return GoLanguage.getCodeList(context);
default: return new ArrayList<>();
}
}
public Set<Character> getLanguageIndentationStarts(LanguageName language) {
switch (language) {
case JAVA: return JavaLanguage.getIndentationStarts();
case PYTHON: return PythonLanguage.getIndentationStarts();
case GO_LANG: return GoLanguage.getIndentationStarts();
default: return new HashSet<>();
}
}
public Set<Character> getLanguageIndentationEnds(LanguageName language) {
switch (language) {
case JAVA: return JavaLanguage.getIndentationEnds();
case PYTHON: return PythonLanguage.getIndentationEnds();
case GO_LANG: return GoLanguage.getIndentationEnds();
default: return new HashSet<>();
}
}
private void applyFiveColorsDarkTheme(LanguageName language) {
switch (language) {
case JAVA:
JavaLanguage.applyFiveColorsDarkTheme(context, codeView);
break;
case PYTHON:
PythonLanguage.applyFiveColorsDarkTheme(context, codeView);
break;
case GO_LANG:
GoLanguage.applyFiveColorsDarkTheme(context, codeView);
break;
}
}
}

View File

@ -0,0 +1,12 @@
package org.mian.gitnex.helpers.codeeditor;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public enum LanguageName {
JAVA,
PYTHON,
GO_LANG
}

View File

@ -0,0 +1,48 @@
package org.mian.gitnex.helpers.codeeditor;
import android.text.Layout;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.widget.EditText;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public class SourcePositionListener {
private final EditText editText;
@FunctionalInterface
public interface OnPositionChanged {
void onPositionChange(int line, int column);
}
private OnPositionChanged onPositionChanged;
public SourcePositionListener(EditText editText) {
this.editText = editText;
editText.setAccessibilityDelegate(viewAccessibility);
}
public void setOnPositionChanged(OnPositionChanged listener) {
onPositionChanged = listener;
}
private final View.AccessibilityDelegate viewAccessibility = new View.AccessibilityDelegate() {
@Override
public void sendAccessibilityEvent(View host, int eventType) {
super.sendAccessibilityEvent(host, eventType);
if (eventType == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED && onPositionChanged != null) {
int selectionStart = editText.getSelectionStart();
Layout layout = editText.getLayout();
if (layout == null) return;
int line = editText.getLayout().getLineForOffset(selectionStart);
int column = selectionStart - editText.getLayout().getLineStart(line);
onPositionChanged.onPositionChange(line + 1, column + 1);
}
}
};
}

View File

@ -0,0 +1,10 @@
package org.mian.gitnex.helpers.codeeditor;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public enum ThemeName {
FIVE_COLOR
}

View File

@ -0,0 +1,100 @@
package org.mian.gitnex.helpers.codeeditor.languages;
import android.content.Context;
import android.content.res.Resources;
import com.amrdeveloper.codeview.Code;
import com.amrdeveloper.codeview.CodeView;
import com.amrdeveloper.codeview.Keyword;
import org.mian.gitnex.R;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public class GoLanguage {
//Language Keywords
private static final Pattern PATTERN_KEYWORDS = Pattern.compile("\\b(break|default|func|interface|case|defer|" +
"go|map|struct|chan|else|goto|package|switch|const" +
"|fallthrough|if|range|type|continue|for|import|return|var|" +
"string|true|false|new|nil|byte|bool|int|int8|int16|int32|int64)\\b");
//Brackets and Colons
private static final Pattern PATTERN_BUILTINS = Pattern.compile("[,:;[->]{}()]");
//Data
private static final Pattern PATTERN_NUMBERS = Pattern.compile("\\b(\\d*[.]?\\d+)\\b");
private static final Pattern PATTERN_CHAR = Pattern.compile("['](.*?)[']");
private static final Pattern PATTERN_STRING = Pattern.compile("[\"](.*?)[\"]");
private static final Pattern PATTERN_HEX = Pattern.compile("0x[0-9a-fA-F]+");
private static final Pattern PATTERN_SINGLE_LINE_COMMENT = Pattern.compile("//[^\\n]*");
private static final Pattern PATTERN_MULTI_LINE_COMMENT = Pattern.compile("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/");
private static final Pattern PATTERN_ATTRIBUTE = Pattern.compile("\\.[a-zA-Z0-9_]+");
private static final Pattern PATTERN_OPERATION =Pattern.compile( ":|==|>|<|!=|>=|<=|->|=|>|<|%|-|-=|%=|\\+|\\-|\\-=|\\+=|\\^|\\&|\\|::|\\?|\\*");
public static void applyFiveColorsDarkTheme(Context context, CodeView codeView) {
codeView.resetSyntaxPatternList();
codeView.resetHighlighter();
Resources resources = context.getResources();
//View Background
codeView.setBackgroundColor(resources.getColor(R.color.five_dark_black, null));
//Syntax Colors
codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.five_dark_yellow, null));
codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.five_dark_yellow, null));
codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.five_dark_white, null));
codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.five_dark_grey, null));
codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.five_dark_grey, null));
codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.five_dark_blue, null));
codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.five_dark_purple, null));
//Default Color
codeView.setTextColor(resources.getColor(R.color.five_dark_white, null));
codeView.reHighlightSyntax();
}
public static String[] getKeywords(Context context) {
return context.getResources().getStringArray(R.array.go_keywords);
}
public static List<Code> getCodeList(Context context) {
List<Code> codeList = new ArrayList<>();
String[] keywords = getKeywords(context);
for (String keyword : keywords) {
codeList.add(new Keyword(keyword));
}
return codeList;
}
public static Set<Character> getIndentationStarts() {
Set<Character> characterSet = new HashSet<>();
characterSet.add('{');
return characterSet;
}
public static Set<Character> getIndentationEnds() {
Set<Character> characterSet = new HashSet<>();
characterSet.add('}');
return characterSet;
}
public static String getCommentStart() {
return "//";
}
public static String getCommentEnd() {
return "";
}
}

View File

@ -0,0 +1,107 @@
package org.mian.gitnex.helpers.codeeditor.languages;
import android.content.Context;
import android.content.res.Resources;
import com.amrdeveloper.codeview.Code;
import com.amrdeveloper.codeview.CodeView;
import com.amrdeveloper.codeview.Keyword;
import org.mian.gitnex.R;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public class JavaLanguage {
//Language Keywords
private static final Pattern PATTERN_KEYWORDS = Pattern.compile("\\b(abstract|boolean|break|byte|case|catch" +
"|char|class|continue|default|do|double|else" +
"|enum|extends|final|finally|float|for|if" +
"|implements|import|instanceof|int|interface" +
"|long|native|new|null|package|private|protected" +
"|public|return|short|static|strictfp|super|switch" +
"|synchronized|this|throw|transient|try|void|volatile|while)\\b");
private static final Pattern PATTERN_BUILTINS = Pattern.compile("[,:;[->]{}()]");
private static final Pattern PATTERN_SINGLE_LINE_COMMENT = Pattern.compile("//[^\\n]*");
private static final Pattern PATTERN_MULTI_LINE_COMMENT = Pattern.compile("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/");
private static final Pattern PATTERN_ATTRIBUTE = Pattern.compile("\\.[a-zA-Z0-9_]+");
private static final Pattern PATTERN_OPERATION =Pattern.compile( ":|==|>|<|!=|>=|<=|->|=|>|<|%|-|-=|%=|\\+|\\-|\\-=|\\+=|\\^|\\&|\\|::|\\?|\\*");
private static final Pattern PATTERN_GENERIC = Pattern.compile("<[a-zA-Z0-9,<>]+>");
private static final Pattern PATTERN_ANNOTATION = Pattern.compile("@.[a-zA-Z0-9]+");
private static final Pattern PATTERN_TODO_COMMENT = Pattern.compile("//TODO[^\n]*");
private static final Pattern PATTERN_NUMBERS = Pattern.compile("\\b(\\d*[.]?\\d+)\\b");
private static final Pattern PATTERN_CHAR = Pattern.compile("['](.*?)[']");
private static final Pattern PATTERN_STRING = Pattern.compile("[\"](.*?)[\"]");
private static final Pattern PATTERN_HEX = Pattern.compile("0x[0-9a-fA-F]+");
public static void applyFiveColorsDarkTheme(Context context, CodeView codeView) {
codeView.resetSyntaxPatternList();
codeView.resetHighlighter();
Resources resources = context.getResources();
//View Background
codeView.setBackgroundColor(resources.getColor(R.color.five_dark_black, null));
//Syntax Colors
codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.five_dark_yellow, null));
codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.five_dark_yellow, null));
codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.five_dark_white, null));
codeView.addSyntaxPattern(PATTERN_SINGLE_LINE_COMMENT, resources.getColor(R.color.five_dark_grey, null));
codeView.addSyntaxPattern(PATTERN_MULTI_LINE_COMMENT, resources.getColor(R.color.five_dark_grey, null));
codeView.addSyntaxPattern(PATTERN_ANNOTATION, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.five_dark_blue, null));
codeView.addSyntaxPattern(PATTERN_GENERIC, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.five_dark_purple, null));
//Default Color
codeView.setTextColor(resources.getColor(R.color.five_dark_white, null));
codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, resources.getColor(R.color.gold, null));
codeView.reHighlightSyntax();
}
public static String[] getKeywords(Context context) {
return context.getResources().getStringArray(R.array.java_keywords);
}
public static List<Code> getCodeList(Context context) {
List<Code> codeList = new ArrayList<>();
String[] keywords = getKeywords(context);
for (String keyword : keywords) {
codeList.add(new Keyword(keyword));
}
return codeList;
}
public static Set<Character> getIndentationStarts() {
Set<Character> characterSet = new HashSet<>();
characterSet.add('{');
return characterSet;
}
public static Set<Character> getIndentationEnds() {
Set<Character> characterSet = new HashSet<>();
characterSet.add('}');
return characterSet;
}
public static String getCommentStart() {
return "//";
}
public static String getCommentEnd() {
return "";
}
}

View File

@ -0,0 +1,99 @@
package org.mian.gitnex.helpers.codeeditor.languages;
import android.content.Context;
import android.content.res.Resources;
import com.amrdeveloper.codeview.Code;
import com.amrdeveloper.codeview.CodeView;
import com.amrdeveloper.codeview.Keyword;
import org.mian.gitnex.R;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
/**
* @author AmrDeveloper
* @author M M Arif
*/
public class PythonLanguage {
//Language Keywords
private static final Pattern PATTERN_KEYWORDS = Pattern.compile("\\b(False|await|else|import|pass|None|break|except|in|raise" +
"|True|class|finally|is|return|and|continue|for|lambda" +
"|try|as|def|from|nonlocal|while|assert|del|global|not" +
"|with|async|elif|if|or|yield)\\b");
//Brackets and Colons
private static final Pattern PATTERN_BUILTINS = Pattern.compile("[,:;[->]{}()]");
//Data
private static final Pattern PATTERN_NUMBERS = Pattern.compile("\\b(\\d*[.]?\\d+)\\b");
private static final Pattern PATTERN_CHAR = Pattern.compile("['](.*?)[']");
private static final Pattern PATTERN_STRING = Pattern.compile("[\"](.*?)[\"]");
private static final Pattern PATTERN_HEX = Pattern.compile("0x[0-9a-fA-F]+");
private static final Pattern PATTERN_TODO_COMMENT = Pattern.compile("#TODO[^\n]*");
private static final Pattern PATTERN_ATTRIBUTE = Pattern.compile("\\.[a-zA-Z0-9_]+");
private static final Pattern PATTERN_OPERATION =Pattern.compile( ":|==|>|<|!=|>=|<=|->|=|>|<|%|-|-=|%=|\\+|\\-|\\-=|\\+=|\\^|\\&|\\|::|\\?|\\*");
private static final Pattern PATTERN_HASH_COMMENT = Pattern.compile("#(?!TODO )[^\\n]*");
public static void applyFiveColorsDarkTheme(Context context, CodeView codeView) {
codeView.resetSyntaxPatternList();
codeView.resetHighlighter();
Resources resources = context.getResources();
//View Background
codeView.setBackgroundColor(resources.getColor(R.color.five_dark_black, null));
//Syntax Colors
codeView.addSyntaxPattern(PATTERN_HEX, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_CHAR, resources.getColor(R.color.five_dark_yellow, null));
codeView.addSyntaxPattern(PATTERN_STRING, resources.getColor(R.color.five_dark_yellow, null));
codeView.addSyntaxPattern(PATTERN_NUMBERS, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_KEYWORDS, resources.getColor(R.color.five_dark_purple, null));
codeView.addSyntaxPattern(PATTERN_BUILTINS, resources.getColor(R.color.five_dark_white, null));
codeView.addSyntaxPattern(PATTERN_HASH_COMMENT, resources.getColor(R.color.five_dark_grey, null));
codeView.addSyntaxPattern(PATTERN_ATTRIBUTE, resources.getColor(R.color.five_dark_blue, null));
codeView.addSyntaxPattern(PATTERN_OPERATION, resources.getColor(R.color.five_dark_purple, null));
//Default Color
codeView.setTextColor(resources.getColor(R.color.five_dark_white, null));
codeView.addSyntaxPattern(PATTERN_TODO_COMMENT, resources.getColor(R.color.gold, null));
codeView.reHighlightSyntax();
}
public static String[] getKeywords(Context context) {
return context.getResources().getStringArray(R.array.python_keywords);
}
public static List<Code> getCodeList(Context context) {
List<Code> codeList = new ArrayList<>();
String[] keywords = getKeywords(context);
for (String keyword : keywords) {
codeList.add(new Keyword(keyword));
}
return codeList;
}
public static Set<Character> getIndentationStarts() {
Set<Character> characterSet = new HashSet<>();
characterSet.add(':');
return characterSet;
}
public static Set<Character> getIndentationEnds() {
return new HashSet<>();
}
public static String getCommentStart() {
return "#";
}
public static String getCommentEnd() {
return "";
}
}

View File

@ -0,0 +1,116 @@
package org.mian.gitnex.viewmodels;
import android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import org.gitnex.tea4j.v2.models.WikiPageMetaData;
import org.json.JSONException;
import org.json.JSONObject;
import org.mian.gitnex.R;
import org.mian.gitnex.adapters.WikiListAdapter;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.databinding.FragmentWikiBinding;
import org.mian.gitnex.helpers.Toasty;
import java.io.IOException;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* @author M M Arif
*/
public class WikiViewModel extends ViewModel {
private MutableLiveData<List<WikiPageMetaData>> wikiList;
public LiveData<List<WikiPageMetaData>> getWiki(String owner, String repo, int page, int resultLimit, Context ctx, FragmentWikiBinding fragmentWikiBinding) {
wikiList = new MutableLiveData<>();
loadWikiList(owner, repo, page, resultLimit, ctx, fragmentWikiBinding);
return wikiList;
}
public void loadWikiList(String owner, String repo, int page, int resultLimit, Context ctx, FragmentWikiBinding fragmentWikiBinding) {
Call<List<WikiPageMetaData>> call;
call = RetrofitClient.getApiInterface(ctx).repoGetWikiPages(owner, repo, page, resultLimit);
call.enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<List<WikiPageMetaData>> call, @NonNull Response<List<WikiPageMetaData>> response) {
if(response.isSuccessful()) {
if(response.code() == 200) {
wikiList.postValue(response.body());
}
}
else if(response.code() == 404) {
fragmentWikiBinding.progressBar.setVisibility(View.GONE);
fragmentWikiBinding.noData.setVisibility(View.VISIBLE);
fragmentWikiBinding.recyclerView.setVisibility(View.GONE);
}
else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
try {
if(response.errorBody() != null) {
new JSONObject(response.errorBody().string());
}
}
catch(IOException | JSONException e) {
fragmentWikiBinding.noData.setText(ctx.getResources().getString(R.string.apiNotFound));
}
}
@Override
public void onFailure(@NonNull Call<List<WikiPageMetaData>> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
}
});
}
public void loadMoreWiki(String owner, String repo, int page, int resultLimit, Context ctx, FragmentWikiBinding fragmentWikiBinding, WikiListAdapter adapter) {
Call<List<WikiPageMetaData>> call;
call = RetrofitClient.getApiInterface(ctx).repoGetWikiPages(owner, repo, page, resultLimit);
call.enqueue(new Callback<>() {
@Override
public void onResponse(@NonNull Call<List<WikiPageMetaData>> call, @NonNull Response<List<WikiPageMetaData>> response) {
if(response.isSuccessful()) {
List<WikiPageMetaData> list = wikiList.getValue();
assert list != null;
assert response.body() != null;
if(response.body().size() != 0) {
list.addAll(response.body());
adapter.updateList(list);
}
else {
adapter.setMoreDataAvailable(false);
}
}
else {
Toasty.error(ctx, ctx.getString(R.string.genericError));
}
}
@Override
public void onFailure(@NonNull Call<List<WikiPageMetaData>> call, @NonNull Throwable t) {
Toasty.error(ctx, ctx.getString(R.string.genericServerResponseError));
}
});
}
}

View File

@ -4,17 +4,8 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,20h9"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M16.5,3.5a2.121,2.121 0,0 1,3 3L7,19l-4,1 1,-4L16.5,3.5z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
android:fillColor="?attr/iconsColor"
android:pathData="m16.6533,1.7224a2.7358,2.7594 0,0 1,3.8676 0l1.6977,1.7124a2.7358,2.7594 0,0 1,0 3.901L8.7587,20.9123c-0.3283,0.3311 -0.7347,0.574 -1.1818,0.7017L2.4946,23.0804A1.1725,1.1826 0,0 1,1.0454 21.6171L2.4977,16.4925A2.7358,2.7594 0,0 1,3.1933 15.2972L16.6533,1.7208ZM18.8638,3.3938a0.3908,0.3942 0,0 0,-0.5534 0l-1.9729,1.9915 2.2496,2.2706 1.9744,-1.9915a0.3908,0.3942 0,0 0,0 -0.5582zM16.9284,9.3274 L14.6788,7.0568 4.852,16.9702A0.3908,0.3942 0,0 0,4.7519 17.1405L3.8796,20.2201 6.9327,19.3402a0.3893,0.3926 0,0 0,0.1688 -0.1009z"
android:strokeWidth="1.57004"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="25dp"
android:viewportWidth="25"
android:viewportHeight="25">
<path
android:pathData="M12.5,12.5m-12.5,0a12.5,12.5 0,1 1,25 0a12.5,12.5 0,1 1,-25 0"
android:fillColor="#89D0E9"/>
<path
android:pathData="M11.972,13.052L10.256,14.792V17H9.368V8.6H10.256V13.676L15.188,8.6H16.208L12.572,12.404L16.46,17H15.404L11.972,13.052Z"
android:fillColor="#486069"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="25dp"
android:viewportWidth="25"
android:viewportHeight="25">
<path
android:pathData="M12.5,12.5m-12.5,0a12.5,12.5 0,1 1,25 0a12.5,12.5 0,1 1,-25 0"
android:fillColor="#F8B6C2"/>
<path
android:pathData="M12.684,17.072C12.06,17.072 11.46,16.972 10.884,16.772C10.316,16.572 9.876,16.308 9.564,15.98L9.912,15.296C10.216,15.6 10.62,15.848 11.124,16.04C11.628,16.224 12.148,16.316 12.684,16.316C13.436,16.316 14,16.18 14.376,15.908C14.752,15.628 14.94,15.268 14.94,14.828C14.94,14.492 14.836,14.224 14.628,14.024C14.428,13.824 14.18,13.672 13.884,13.568C13.588,13.456 13.176,13.336 12.648,13.208C12.016,13.048 11.512,12.896 11.136,12.752C10.76,12.6 10.436,12.372 10.164,12.068C9.9,11.764 9.768,11.352 9.768,10.832C9.768,10.408 9.88,10.024 10.104,9.68C10.328,9.328 10.672,9.048 11.136,8.84C11.6,8.632 12.176,8.528 12.864,8.528C13.344,8.528 13.812,8.596 14.268,8.732C14.732,8.86 15.132,9.04 15.468,9.272L15.168,9.98C14.816,9.748 14.44,9.576 14.04,9.464C13.64,9.344 13.248,9.284 12.864,9.284C12.128,9.284 11.572,9.428 11.196,9.716C10.828,9.996 10.644,10.36 10.644,10.808C10.644,11.144 10.744,11.416 10.944,11.624C11.152,11.824 11.408,11.98 11.712,12.092C12.024,12.196 12.44,12.312 12.96,12.44C13.576,12.592 14.072,12.744 14.448,12.896C14.832,13.04 15.156,13.264 15.42,13.568C15.684,13.864 15.816,14.268 15.816,14.78C15.816,15.204 15.7,15.592 15.468,15.944C15.244,16.288 14.896,16.564 14.424,16.772C13.952,16.972 13.372,17.072 12.684,17.072Z"
android:fillColor="#486069"/>
</vector>

View File

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M2,3h6a4,4 0,0 1,4 4v14a3,3 0,0 0,-3 -3H2z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
<path
android:pathData="M22,3h-6a4,4 0,0 0,-4 4v14a3,3 0,0 1,3 -3h7z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="?attr/iconsColor"
android:strokeLineCap="round"/>
</vector>

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
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:background="?android:attr/selectableItemBackgroundBorderless"
android:focusable="true"
android:clickable="true"
android:src="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/codeEditor"
android:textColor="?attr/primaryTextColor"
android:maxLines="1"
android:textSize="20sp" />
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
<com.amrdeveloper.codeview.CodeView
android:id="@+id/codeView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="56dp"
android:layout_above="@+id/source_info_layout"
android:background="@color/colorPrimary"
android:dropDownWidth="@dimen/dimen150dp"
android:dropDownHorizontalOffset="0dp"
android:dropDownSelector="@color/colorPrimary"
android:textSize="14sp"
android:gravity="top|start" />
<RelativeLayout
android:id="@+id/source_info_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen32dp"
android:layout_alignParentBottom="true"
android:background="@color/black">
<TextView
android:id="@+id/language_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_marginStart="@dimen/dimen8dp"
android:gravity="center"
android:textColor="@color/colorAccent"
android:textSize="@dimen/dimen14sp"
tools:text="Java" />
<TextView
android:id="@+id/source_position"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/dimen8dp"
android:gravity="center"
android:textColor="@color/colorAccent"
android:textSize="@dimen/dimen14sp"
tools:text="0:0"
tools:ignore="RelativeOverlap" />
</RelativeLayout>
</RelativeLayout>

View File

@ -55,7 +55,6 @@
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
app:tabMode="scrollable"
android:visibility="gone"
app:tabTextAppearance="@style/customTabLayout"
android:layout_width="match_parent"
android:background="?attr/primaryBackgroundColor"
@ -63,62 +62,13 @@
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabItem
android:id="@+id/tab_item_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tabTextInfo" />
<com.google.android.material.tabs.TabItem
android:id="@+id/tab_item_files"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tabTextFiles" />
<com.google.android.material.tabs.TabItem
android:id="@+id/tab_item_issues"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pageTitleIssues" />
<com.google.android.material.tabs.TabItem
android:id="@+id/tab_item_pull_requests"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tabPullRequests" />
<com.google.android.material.tabs.TabItem
android:id="@+id/tab_item_releases"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tabTextReleases" />
<com.google.android.material.tabs.TabItem
android:id="@+id/tab_item_ml"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tabTextMl" />
<com.google.android.material.tabs.TabItem
android:id="@+id/tab_item_labels"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/newIssueLabelsTitle" />
<com.google.android.material.tabs.TabItem
android:id="@+id/tab_item_collaborators"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tabTextCollaborators" />
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/container"
android:visibility="gone"
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/repositoryContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,188 @@
<?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="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="?attr/primaryBackgroundColor">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
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:background="?android:attr/selectableItemBackgroundBorderless"
android:focusable="true"
android:clickable="true"
android:src="@drawable/ic_close" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/defaultFilename"
android:textColor="?attr/primaryTextColor"
android:ellipsize="none"
android:scrollbars="horizontal"
android:singleLine="true"
android:layout_marginEnd="20dp"
android:textSize="18sp" />
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/render_wiki"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="vertical">
<LinearLayout
android:id="@+id/markdown_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical"
android:paddingTop="0dp"
android:paddingBottom="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:visibility="gone">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/markdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:textSize="14sp" />
</LinearLayout>
<org.mian.gitnex.views.SyntaxHighlightedArea
android:id="@+id/contents"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
<LinearLayout
android:id="@+id/create_wiki"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="0dp"
android:paddingBottom="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/title_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
app:hintTextColor="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:endIconMode="clear_text"
app:endIconTint="?attr/iconsColor"
android:hint="@string/newIssueTitle">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/wiki_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:inputType="textCapSentences"
android:singleLine="true"
android:imeOptions="actionNext"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:boxBackgroundColor="?attr/inputBackgroundColor"
android:textColorHint="?attr/hintColor"
app:hintTextColor="?attr/hintColor"
app:boxStrokeErrorColor="@color/darkRed"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/wiki_content"
android:layout_width="match_parent"
android:layout_height="480dp"
android:textColor="?attr/inputTextColor"
android:textColorHighlight="?attr/hintColor"
android:textColorHint="?attr/hintColor"
android:gravity="top|start"
android:singleLine="false"
android:imeOptions="actionNext"
android:textSize="14sp" />
</com.google.android.material.textfield.TextInputLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/markdown_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textIsSelectable="true"
android:layout_marginTop="@dimen/dimen8dp"
android:layout_marginBottom="@dimen/dimen8dp"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@ -49,7 +49,7 @@
android:id="@+id/createNewUser"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/deleteAllDrafts"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/editFile"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/deleteFile"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -75,7 +75,7 @@
android:id="@+id/downloadFile"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -64,7 +64,7 @@
android:id="@+id/commentMenuEdit"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -77,7 +77,7 @@
android:id="@+id/commentMenuDelete"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -90,7 +90,7 @@
android:id="@+id/commentMenuQuote"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -103,7 +103,7 @@
android:id="@+id/commentMenuCopy"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -134,7 +134,7 @@
android:id="@+id/issueCommentCopyUrl"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -147,7 +147,7 @@
android:id="@+id/issueCommentShare"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -160,7 +160,7 @@
android:id="@+id/open"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/filterByMilestone"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/openIssues"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -75,7 +75,7 @@
android:id="@+id/closedIssues"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/labelMenuEdit"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/labelMenuDelete"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/openMilestone"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/closedMilestone"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/closeMilestone"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/openMilestone"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/openMyIssues"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/closedMyIssues"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -75,7 +75,7 @@
android:id="@+id/assignedToMe"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"

View File

@ -48,7 +48,7 @@
android:id="@+id/markPinned"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -61,7 +61,7 @@
android:id="@+id/markRead"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -74,7 +74,7 @@
android:id="@+id/markUnread"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/unreadNotifications"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/readNotifications"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/createRepository"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/createTeam"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -75,7 +75,7 @@
android:id="@+id/createLabel"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"

View File

@ -49,7 +49,7 @@
android:id="@+id/addRepo"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/addNewMember"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/addNewEmailAddress"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/openPr"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/closedPr"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/deleteRelease"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/releases"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/tags"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/newFile"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/createNewIssue"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -75,7 +75,7 @@
android:id="@+id/createLabel"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -88,7 +88,7 @@
android:id="@+id/createNewMilestone"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -101,7 +101,7 @@
android:id="@+id/createRelease"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -114,7 +114,7 @@
android:id="@+id/createPullRequest"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -127,7 +127,7 @@
android:id="@+id/addCollaborator"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -136,6 +136,19 @@
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<TextView
android:id="@+id/create_wiki"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
app:drawableTopCompat="@drawable/ic_wiki"
android:text="@string/wiki"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
</com.google.android.flexbox.FlexboxLayout>
<View
@ -176,7 +189,7 @@
android:id="@+id/starRepository"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -189,7 +202,7 @@
android:id="@+id/unStarRepository"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -202,7 +215,7 @@
android:id="@+id/watchRepository"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -215,7 +228,7 @@
android:id="@+id/unWatchRepository"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -228,7 +241,7 @@
android:id="@+id/copyRepoUrl"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -241,7 +254,7 @@
android:id="@+id/shareRepository"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -254,7 +267,7 @@
android:id="@+id/openWebRepo"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"
@ -267,7 +280,7 @@
android:id="@+id/repoSettings"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
app:layout_alignSelf="flex_start"
android:gravity="center"

View File

@ -64,7 +64,7 @@
android:id="@+id/openFilesDiff"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -78,7 +78,7 @@
android:id="@+id/mergePullRequest"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -92,7 +92,7 @@
android:id="@+id/updatePullRequest"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -106,7 +106,7 @@
android:id="@+id/deletePrHeadBranch"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -119,7 +119,7 @@
android:id="@+id/editIssue"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -132,7 +132,7 @@
android:id="@+id/addRemoveAssignees"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -145,7 +145,7 @@
android:id="@+id/editLabels"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -158,7 +158,7 @@
android:id="@+id/subscribeIssue"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -171,7 +171,7 @@
android:id="@+id/unsubscribeIssue"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -185,7 +185,7 @@
android:id="@+id/closeIssue"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -216,7 +216,7 @@
android:id="@+id/copyIssueUrl"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -229,7 +229,7 @@
android:id="@+id/shareIssue"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -242,7 +242,7 @@
android:id="@+id/open"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/tagMenuDelete"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -49,7 +49,7 @@
android:id="@+id/followUser"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
@ -62,7 +62,7 @@
android:id="@+id/unfollowUser"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="8dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="6dp"
android:paddingBottom="12dp"
android:background="?attr/primaryBackgroundColor">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/wiki_list_head_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/bottom_sheet_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/wiki"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
</LinearLayout>
<com.google.android.flexbox.FlexboxLayout
android:id="@+id/wiki_list_section"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:flexWrap="wrap"
app:alignItems="stretch"
android:padding="8dp"
app:alignContent="stretch" >
<TextView
android:id="@+id/edit_wiki"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
app:drawableTopCompat="@drawable/ic_edit"
android:text="@string/menuEditText"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<TextView
android:id="@+id/delete_wiki"
android:layout_width="98dp"
android:layout_height="100dp"
android:padding="4dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
app:layout_alignSelf="flex_start"
app:drawableTopCompat="@drawable/ic_delete"
android:text="@string/menuDeleteText"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
</com.google.android.flexbox.FlexboxLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".activities.RepoDetailActivity">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/pull_to_refresh"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor"
android:scrollbars="vertical" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
style="@style/Widget.MaterialComponents.LinearProgressIndicator"
app:indicatorColor="?attr/progressIndicatorColor" />
<TextView
android:id="@+id/no_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"
android:gravity="center"
android:text="@string/noDataFound"
android:textColor="?attr/primaryTextColor"
android:textSize="18sp"
android:visibility="gone" />
</RelativeLayout>

View File

@ -0,0 +1,16 @@
<?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">
<TextView
android:id="@+id/suggestItemTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
android:padding="@dimen/dimen24dp"
android:textColor="@color/gold"
android:textSize="@dimen/dimen16sp"
tools:text="Keyword" />
</LinearLayout>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/autocomplete_background">
<RelativeLayout
android:id="@+id/code_container"
android:layout_width="@dimen/dimen40dp"
android:layout_height="@dimen/dimen50dp">
<ImageView
android:id="@+id/code_type"
android:layout_width="@dimen/dimen24dp"
android:layout_height="@dimen/dimen24dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_keyword"
android:textColor="@color/colorWhite"
android:textSize="@dimen/dimen20sp"
android:textStyle="bold"
tools:text="K"
android:contentDescription="@string/generalImgContentText" />
</RelativeLayout>
<TextView
android:id="@+id/code_title"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen40dp"
android:layout_toEndOf="@id/code_container"
android:gravity="start|center_vertical"
android:paddingStart="@dimen/dimen4dp"
android:paddingEnd="@dimen/dimen4dp"
android:textColor="@color/colorWhite"
tools:ignore="RtlSymmetry"
tools:text="Keyword" />
</RelativeLayout>

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:focusable="true"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:id="@+id/wiki_info_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:gravity="center_vertical"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/image_avatar"
android:layout_width="@dimen/list_avatar_size"
android:layout_height="@dimen/list_avatar_size"
android:layout_marginStart="0dp"
android:layout_marginEnd="10dp"
android:contentDescription="@string/wiki"
android:src="@drawable/ic_android" />
<TextView
android:id="@+id/page_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
android:text="@string/wiki" />
</LinearLayout>
<View
android:id="@+id/spacerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp" />
<LinearLayout
android:id="@+id/wiki_detail_info_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/wiki_last_updated_by"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/hintColor"
android:textSize="13sp"
android:text="@string/wikiAuthor" />
<LinearLayout
android:id="@+id/wiki_menu_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:gravity="center_vertical|end"
android:orientation="horizontal"
android:paddingLeft="5dp"
android:paddingRight="5dp">
<ImageView
android:id="@+id/wiki_menu"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="3dp"
android:layout_marginEnd="0dp"
android:contentDescription="@string/generalImgContentText"
app:srcCompat="@drawable/ic_dotted_menu_horizontal"
app:tint="?attr/iconsColor" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/edit"
android:icon="@drawable/ic_edit"
android:title="@string/menuEditText"
android:orderInCategory="1"
app:showAsAction="ifRoom" />
</menu>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/save"
android:icon="@drawable/ic_save"
android:title="@string/saveButton"
android:orderInCategory="1"
app:showAsAction="ifRoom" />
</menu>

View File

@ -58,4 +58,14 @@
<color name="pitchBlackThemeTextColor">#d2d2d2</color>
<color name="pitchBlackThemeDividerColor">#0E0E0E</color>
<color name="pitchBlackThemeGeneralBackgroundColor">#151515</color>
<!-- code editor colors -->
<color name="five_dark_black">#252526</color>
<color name="five_dark_blue">#267ae9</color>
<color name="five_dark_yellow">#fde92f</color>
<color name="five_dark_purple">#eb84f3</color>
<color name="five_dark_grey">#a9b1ae</color>
<color name="five_dark_white">#ffffff</color>
<color name="gold">#e6b121</color>
<color name="autocomplete_background">#0c0c0c</color>
</resources>

View File

@ -6,4 +6,24 @@
<dimen name="list_avatar_size">24dp</dimen>
<dimen name="list_avatar_size_medium">34dp</dimen>
<dimen name="list_avatar_size_large">60dp</dimen>
<!--DP-->
<dimen name="dimen4dp">4dp</dimen>
<dimen name="dimen8dp">8dp</dimen>
<dimen name="dimen16dp">16dp</dimen>
<dimen name="dimen20dp">20dp</dimen>
<dimen name="dimen24dp">24dp</dimen>
<dimen name="dimen32dp">32dp</dimen>
<dimen name="dimen40dp">40dp</dimen>
<dimen name="dimen50dp">50dp</dimen>
<dimen name="dimen80dp">80dp</dimen>
<dimen name="dimen120dp">12dp</dimen>
<dimen name="dimen150dp">150dp</dimen>
<!--SP-->
<dimen name="dimen12sp">12sp</dimen>
<dimen name="dimen14sp">14sp</dimen>
<dimen name="dimen16sp">16sp</dimen>
<dimen name="dimen18sp">18sp</dimen>
<dimen name="dimen20sp">20sp</dimen>
</resources>

View File

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--Java Keywords List-->
<string-array name="java_keywords">
<item>public</item>
<item>private</item>
<item>protected</item>
<item>package</item>
<item>abstract</item>
<item>boolean</item>
<item>break</item>
<item>byte</item>
<item>case</item>
<item>catch</item>
<item>char</item>
<item>class</item>
<item>continue</item>
<item>default</item>
<item>do</item>
<item>double</item>
<item>else</item>
<item>enum</item>
<item>extends</item>
<item>final</item>
<item>finally</item>
<item>float</item>
<item>for</item>
<item>if</item>
<item>implements</item>
<item>import</item>
<item>instanceof</item>
<item>int</item>
<item>interface</item>
<item>long</item>
<item>native</item>
<item>new</item>
<item>return</item>
<item>short</item>
<item>static</item>
<item>strictfp</item>
<item>super</item>
<item>switch</item>
<item>synchronized</item>
<item>this</item>
<item>throw</item>
<item>transient</item>
<item>try</item>
<item>void</item>
<item>volatile</item>
<item>while</item>
</string-array>
<!--GoLang Keywords List-->
<string-array name="go_keywords">
<item>break</item>
<item>default</item>
<item>func</item>
<item>interface</item>
<item>select</item>
<item>case</item>
<item>defer</item>
<item>go</item>
<item>map</item>
<item>struct</item>
<item>chan</item>
<item>else</item>
<item>goto</item>
<item>package</item>
<item>switch</item>
<item>const</item>
<item>fallthrough</item>
<item>if</item>
<item>bool</item>
<item>byte</item>
<item>cap</item>
<item>close</item>
<item>complex</item>
<item>complex64</item>
<item>complex128</item>
<item>uint16</item>
<item>copy</item>
<item>false</item>
<item>float32</item>
<item>float64</item>
<item>imag</item>
<item>int</item>
<item>int8</item>
<item>int16</item>
<item>uint32</item>
<item>int32</item>
<item>int64</item>
<item>len</item>
<item>make</item>
<item>new</item>
<item>nil</item>
<item>uint64</item>
<item>range</item>
<item>type</item>
<item>continue</item>
<item>for</item>
<item>import</item>
<item>return</item>
<item>var</item>
</string-array>
<!--Python Keywords List-->
<string-array name="python_keywords">
<item>False</item>
<item>await</item>
<item>else</item>
<item>import</item>
<item>pass</item>
<item>None</item>
<item>break</item>
<item>except</item>
<item>in</item>
<item>raise</item>
<item>True</item>
<item>class</item>
<item>finally</item>
<item>is</item>
<item>return</item>
<item>and</item>
<item>continue</item>
<item>for</item>
<item>lambda</item>
<item>try</item>
<item>as</item>
<item>def</item>
<item>from</item>
<item>nonlocal</item>
<item>while</item>
<item>assert</item>
<item>del</item>
<item>global</item>
<item>not</item>
<item>with</item>
<item>async</item>
<item>elif</item>
<item>if</item>
<item>or</item>
<item>yield</item>
</string-array>
</resources>

View File

@ -1,7 +1,7 @@
<resources>
<string name="appName" translatable="false">GitNex</string>
<string name="appEmail" translatable="false">gitnex@swatian.com</string>
<string name="appEmail" translatable="false">hello@gitnex.com</string>
<string name="appRepo" translatable="false">Source code</string>
<string name="appRepoLink" translatable="false">https://codeberg.org/gitnex/GitNex</string>
<string name="appWebsiteLink" translatable="false">https://gitnex.com/</string>
@ -766,4 +766,18 @@
<string name="repoAdopted">Adopted repository %s</string>
<string name="unadoptedRepos">Unadopted Repositories</string>
<string name="unadoptedReposMessage">- Adopt will add repository %s to organization/user %s.\n- Delete will remove it from the system.</string>
<!-- wiki -->
<string name="wiki">Wiki</string>
<string name="wikiAuthor"><![CDATA[<b>%1$s</b> updated %2$s]]></string>
<string name="deleteWikiPageMessage">Do you really want to delete %s?</string>
<string name="wikiPageDeleted">Wiki page deleted successfully</string>
<string name="wikiPageNameAndContentError">Page name and page content can\'t be empty</string>
<string name="createWikiPage">Create Wiki Page</string>
<string name="wikiUpdated">Wiki page updated successfully</string>
<string name="wikiCreated">Wiki page created successfully</string>
<!-- code editor -->
<string name="sourcePosition" translatable="false">%1$d:%2$d</string>
<string name="codeEditor" translatable="false">Code Editor</string>
</resources>