Merge branch '43-file-browser' of mmarif/GitNex into master
@ -6,8 +6,8 @@ android {
|
||||
applicationId "org.mian.gitnex"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 60
|
||||
versionName "2.1.0"
|
||||
versionCode 63
|
||||
versionName "2.1.3"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
@ -24,7 +24,7 @@ android {
|
||||
|
||||
dependencies {
|
||||
def lifecycle_version = "2.2.0-alpha05"
|
||||
final def markwon_version = "4.1.1"
|
||||
final def markwon_version = "4.1.1"
|
||||
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
|
@ -11,8 +11,11 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".activities.NewFileActivity"
|
||||
android:name=".activities.FileViewActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar"></activity>
|
||||
<activity
|
||||
android:name=".activities.NewFileActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".activities.RepoWatchersActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
@ -64,8 +67,8 @@
|
||||
<activity android:name=".activities.NewOrganizationActivity" />
|
||||
<activity android:name=".activities.OpenRepoInBrowserActivity" />
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
</manifest>
|
@ -0,0 +1,147 @@
|
||||
package org.mian.gitnex.activities;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.helpers.AlertDialogs;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import org.mian.gitnex.models.Files;
|
||||
import org.mian.gitnex.util.AppUtil;
|
||||
import org.mian.gitnex.util.TinyDB;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class FileViewActivity extends AppCompatActivity {
|
||||
|
||||
private View.OnClickListener onClickListener;
|
||||
private TextView singleFileContents;
|
||||
final Context ctx = this;
|
||||
private ProgressBar mProgressBar;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_file_view);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
final TinyDB tinyDb = new TinyDB(getApplicationContext());
|
||||
String repoFullName = tinyDb.getString("repoFullName");
|
||||
String[] parts = repoFullName.split("/");
|
||||
final String repoOwner = parts[0];
|
||||
final String repoName = parts[1];
|
||||
final String instanceUrl = tinyDb.getString("instanceUrl");
|
||||
final String loginUid = tinyDb.getString("loginUid");
|
||||
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
|
||||
|
||||
boolean connToInternet = AppUtil.haveNetworkConnection(getApplicationContext());
|
||||
|
||||
ImageView closeActivity = findViewById(R.id.close);
|
||||
singleFileContents = findViewById(R.id.singleFileContents);
|
||||
singleFileContents.setVisibility(View.GONE);
|
||||
mProgressBar = findViewById(R.id.progress_bar);
|
||||
|
||||
String singleFileName = getIntent().getStringExtra("singleFileName");
|
||||
|
||||
TextView toolbar_title = findViewById(R.id.toolbar_title);
|
||||
toolbar_title.setText(singleFileName);
|
||||
|
||||
initCloseListener();
|
||||
closeActivity.setOnClickListener(onClickListener);
|
||||
|
||||
if(connToInternet) {
|
||||
getSingleFileContents(instanceUrl, instanceToken, repoOwner, repoName, singleFileName);
|
||||
}
|
||||
else {
|
||||
Toasty.info(getApplicationContext(), getString(R.string.checkNetConnection));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void getSingleFileContents(String instanceUrl, String token, final String owner, String repo, final String filename) {
|
||||
|
||||
Call<Files> call = RetrofitClient
|
||||
.getInstance(instanceUrl)
|
||||
.getApiInterface()
|
||||
.getSingleFileContents(token, owner, repo, filename);
|
||||
|
||||
call.enqueue(new Callback<Files>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<Files> call, @NonNull retrofit2.Response<Files> response) {
|
||||
|
||||
if (response.code() == 200) {
|
||||
|
||||
AppUtil appUtil = new AppUtil();
|
||||
assert response.body() != null;
|
||||
|
||||
if(!response.body().getContent().equals("")) {
|
||||
singleFileContents.setVisibility(View.VISIBLE);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
singleFileContents.setText(appUtil.decodeBase64(response.body().getContent()));
|
||||
}
|
||||
else {
|
||||
singleFileContents.setText("");
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
}
|
||||
else if(response.code() == 401) {
|
||||
|
||||
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
|
||||
getResources().getString(R.string.alertDialogTokenRevokedMessage),
|
||||
getResources().getString(R.string.alertDialogTokenRevokedCopyNegativeButton),
|
||||
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
|
||||
|
||||
}
|
||||
else if(response.code() == 403) {
|
||||
|
||||
Toasty.info(ctx, ctx.getString(R.string.authorizeError));
|
||||
|
||||
}
|
||||
else if(response.code() == 404) {
|
||||
|
||||
Toasty.info(ctx, ctx.getString(R.string.apiNotFound));
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
Toasty.info(getApplicationContext(), getString(R.string.labelGeneralError));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<Files> call, @NonNull Throwable t) {
|
||||
Log.e("onFailure", t.toString());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void initCloseListener() {
|
||||
onClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
getIntent().removeExtra("singleFileName");
|
||||
finish();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -354,9 +354,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||
|
||||
userAvatar = hView.findViewById(R.id.userAvatar);
|
||||
if (!Objects.requireNonNull(userDetails).getAvatar().equals("")) {
|
||||
Picasso.get().load(userDetails.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(userAvatar);
|
||||
Picasso.get().load(userDetails.getAvatar()).transform(new RoundedTransformation(8, 0)).resize(160, 160).centerCrop().into(userAvatar);
|
||||
} else {
|
||||
userAvatar.setImageResource(R.mipmap.ic_launcher_round);
|
||||
userAvatar.setImageResource(R.mipmap.app_logo_round);
|
||||
}
|
||||
|
||||
userFullName = hView.findViewById(R.id.userFullname);
|
||||
|
@ -26,6 +26,7 @@ import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.fragments.BranchesFragment;
|
||||
import org.mian.gitnex.fragments.ClosedIssuesFragment;
|
||||
import org.mian.gitnex.fragments.CollaboratorsFragment;
|
||||
import org.mian.gitnex.fragments.FilesFragment;
|
||||
import org.mian.gitnex.fragments.IssuesFragment;
|
||||
import org.mian.gitnex.fragments.LabelsFragment;
|
||||
import org.mian.gitnex.fragments.MilestonesFragment;
|
||||
@ -87,9 +88,9 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
|
||||
if(!tinyDb.getString("issuesCounter").isEmpty()) {
|
||||
getRepoInfo(instanceUrl, Authorization.returnAuthentication(getApplicationContext(), loginUid, instanceToken), repoOwner, repoName1);
|
||||
}
|
||||
Objects.requireNonNull(tabLayout.getTabAt(1)).setCustomView(tabHeader);
|
||||
Objects.requireNonNull(tabLayout.getTabAt(2)).setCustomView(tabHeader);
|
||||
|
||||
TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(1);
|
||||
TabLayout.Tab tabOpenIssues = tabLayout.getTabAt(2);
|
||||
ColorStateList textColor = tabLayout.getTabTextColors();
|
||||
assert tabOpenIssues != null;
|
||||
TextView openIssueTabView = Objects.requireNonNull(tabOpenIssues.getCustomView()).findViewById(R.id.counterBadgeText);
|
||||
@ -199,21 +200,23 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
|
||||
switch (position) {
|
||||
case 0: // information
|
||||
return RepoInfoFragment.newInstance(repoOwner, repoName);
|
||||
case 1: // issues
|
||||
case 1: // files
|
||||
return FilesFragment.newInstance(repoOwner, repoName);
|
||||
case 2: // issues
|
||||
fragment = new IssuesFragment();
|
||||
break;
|
||||
case 2: // closed issues
|
||||
case 3: // closed issues
|
||||
fragment = new ClosedIssuesFragment();
|
||||
break;
|
||||
case 3: // milestones
|
||||
case 4: // milestones
|
||||
return MilestonesFragment.newInstance(repoOwner, repoName);
|
||||
case 4: // labels
|
||||
case 5: // labels
|
||||
return LabelsFragment.newInstance(repoOwner, repoName);
|
||||
case 5: // branches
|
||||
case 6: // branches
|
||||
return BranchesFragment.newInstance(repoOwner, repoName);
|
||||
case 6: // releases
|
||||
case 7: // releases
|
||||
return ReleasesFragment.newInstance(repoOwner, repoName);
|
||||
case 7: // collaborators
|
||||
case 8: // collaborators
|
||||
return CollaboratorsFragment.newInstance(repoOwner, repoName);
|
||||
}
|
||||
return fragment;
|
||||
@ -221,7 +224,7 @@ public class RepoDetailActivity extends AppCompatActivity implements RepoBottomS
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 8;
|
||||
return 9;
|
||||
}
|
||||
|
||||
}
|
||||
|
211
app/src/main/java/org/mian/gitnex/adapters/FilesAdapter.java
Normal file
@ -0,0 +1,211 @@
|
||||
package org.mian.gitnex.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.activities.FileViewActivity;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import org.mian.gitnex.models.Files;
|
||||
import org.mian.gitnex.util.TinyDB;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class FilesAdapter extends RecyclerView.Adapter<FilesAdapter.FilesViewHolder> implements Filterable {
|
||||
|
||||
private List<Files> filesList;
|
||||
private Context mCtx;
|
||||
private List<Files> filesListFull;
|
||||
|
||||
class FilesViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private ImageView fileTypeImage;
|
||||
private TextView fileName;
|
||||
private TextView fileType;
|
||||
|
||||
private FilesViewHolder(View itemView) {
|
||||
|
||||
super(itemView);
|
||||
fileName = itemView.findViewById(R.id.fileName);
|
||||
fileTypeImage = itemView.findViewById(R.id.fileImage);
|
||||
fileType = itemView.findViewById(R.id.fileType);
|
||||
|
||||
//ImageView filesDropdownMenu = itemView.findViewById(R.id.filesDropdownMenu);
|
||||
|
||||
fileName.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
Context context = v.getContext();
|
||||
TinyDB tinyDb = new TinyDB(context);
|
||||
|
||||
if(fileType.getText().toString().equals("file")) {
|
||||
Intent intent = new Intent(context, FileViewActivity.class);
|
||||
intent.putExtra("singleFileName", fileName.getText().toString());
|
||||
context.startActivity(intent);
|
||||
}
|
||||
else if(fileType.getText().toString().equals("dir")) {
|
||||
//tinyDb.putString("filesDir", fileName.getText().toString());
|
||||
Toasty.info(context, context.getString(R.string.filesDirNotSupportedYet));
|
||||
}
|
||||
else {
|
||||
Toasty.info(context, context.getString(R.string.filesGenericError));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/*filesDropdownMenu.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
final Context context = v.getContext();
|
||||
Context context_ = new ContextThemeWrapper(context, R.style.popupMenuStyle);
|
||||
|
||||
PopupMenu popupMenu = new PopupMenu(context_, v);
|
||||
popupMenu.inflate(R.menu.files_dotted_list_menu);
|
||||
|
||||
Object menuHelper;
|
||||
Class[] argTypes;
|
||||
try {
|
||||
|
||||
Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup");
|
||||
fMenuHelper.setAccessible(true);
|
||||
menuHelper = fMenuHelper.get(popupMenu);
|
||||
argTypes = new Class[] { boolean.class };
|
||||
menuHelper.getClass().getDeclaredMethod("setForceShowIcon",
|
||||
argTypes).invoke(menuHelper, true);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
popupMenu.show();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.deleteFile:
|
||||
|
||||
Intent intent = new Intent(context, DeleteFileActivity.class);
|
||||
intent.putExtra("repoFullNameForDeleteFile", fullName.getText());
|
||||
context.startActivity(intent);
|
||||
break;
|
||||
|
||||
case R.id.editFile:
|
||||
|
||||
Intent intentW = new Intent(context, EditFileActivity.class);
|
||||
intentW.putExtra("repoFullNameForEditFile", fullName.getText());
|
||||
context.startActivity(intentW);
|
||||
break;
|
||||
|
||||
case R.id.openInBrowser:
|
||||
|
||||
Intent intentOpenInBrowser = new Intent(context, OpenFileInBrowserActivity.class);
|
||||
intentOpenInBrowser.putExtra("fileFullNameBrowser", fullName.getText());
|
||||
context.startActivity(intentOpenInBrowser);
|
||||
break;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
popupMenu.show();
|
||||
|
||||
}
|
||||
});*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public FilesAdapter(Context mCtx, List<Files> filesListMain) {
|
||||
this.mCtx = mCtx;
|
||||
this.filesList = filesListMain;
|
||||
filesListFull = new ArrayList<>(filesList);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public FilesAdapter.FilesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.files_list, parent, false);
|
||||
return new FilesAdapter.FilesViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull FilesAdapter.FilesViewHolder holder, int position) {
|
||||
|
||||
Files currentItem = filesList.get(position);
|
||||
|
||||
holder.fileType.setText(currentItem.getType());
|
||||
holder.fileName.setText(currentItem.getName());
|
||||
|
||||
if(currentItem.getType().equals("file")) {
|
||||
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_file_new));
|
||||
}
|
||||
else if(currentItem.getType().equals("dir")) {
|
||||
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_folder_24));
|
||||
}
|
||||
else {
|
||||
holder.fileTypeImage.setImageDrawable(mCtx.getResources().getDrawable(R.drawable.ic_question_mark_24));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return filesList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
return filesFilter;
|
||||
}
|
||||
|
||||
private Filter filesFilter = new Filter() {
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
List<Files> filteredList = new ArrayList<>();
|
||||
|
||||
if (constraint == null || constraint.length() == 0) {
|
||||
filteredList.addAll(filesListFull);
|
||||
} else {
|
||||
String filterPattern = constraint.toString().toLowerCase().trim();
|
||||
|
||||
for (Files item : filesListFull) {
|
||||
if (item.getName().toLowerCase().contains(filterPattern) || item.getPath().toLowerCase().contains(filterPattern)) {
|
||||
filteredList.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FilterResults results = new FilterResults();
|
||||
results.values = filteredList;
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void publishResults(CharSequence constraint, FilterResults results) {
|
||||
filesList.clear();
|
||||
filesList.addAll((List) results.values);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -237,6 +237,7 @@ public class MilestonesAdapter extends RecyclerView.Adapter<MilestonesAdapter.Mi
|
||||
|
||||
if (currentItem.getOpen_issues() == 0) {
|
||||
holder.msProgress.setProgress(100);
|
||||
holder.msProgress.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.milestoneCompletion, 100), mCtx));
|
||||
}
|
||||
else {
|
||||
int msCompletion = 100 * currentItem.getClosed_issues() / (currentItem.getOpen_issues() + currentItem.getClosed_issues());
|
||||
|
@ -179,9 +179,14 @@ public class MyReposListAdapter extends RecyclerView.Adapter<MyReposListAdapter.
|
||||
.endConfig()
|
||||
.buildRoundRect(firstCharacter, color, 3);
|
||||
|
||||
if (!currentItem.getAvatar_url().equals("")) {
|
||||
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.imageMy);
|
||||
} else {
|
||||
if (currentItem.getAvatar_url() != null) {
|
||||
if (!currentItem.getAvatar_url().equals("")) {
|
||||
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.imageMy);
|
||||
} else {
|
||||
holder.imageMy.setImageDrawable(drawable);
|
||||
}
|
||||
}
|
||||
else {
|
||||
holder.imageMy.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
|
@ -181,9 +181,14 @@ public class ReposListAdapter extends RecyclerView.Adapter<ReposListAdapter.Repo
|
||||
.endConfig()
|
||||
.buildRoundRect(firstCharacter, color, 3);
|
||||
|
||||
if (!currentItem.getAvatar_url().equals("")) {
|
||||
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
|
||||
} else {
|
||||
if (currentItem.getAvatar_url() != null) {
|
||||
if (!currentItem.getAvatar_url().equals("")) {
|
||||
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
|
||||
} else {
|
||||
holder.image.setImageDrawable(drawable);
|
||||
}
|
||||
}
|
||||
else {
|
||||
holder.image.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
|
@ -180,9 +180,14 @@ public class RepositoriesByOrgAdapter extends RecyclerView.Adapter<RepositoriesB
|
||||
.endConfig()
|
||||
.buildRoundRect(firstCharacter, color, 3);
|
||||
|
||||
if (!currentItem.getAvatar_url().equals("")) {
|
||||
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
|
||||
} else {
|
||||
if (currentItem.getAvatar_url() != null) {
|
||||
if (!currentItem.getAvatar_url().equals("")) {
|
||||
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
|
||||
} else {
|
||||
holder.image.setImageDrawable(drawable);
|
||||
}
|
||||
}
|
||||
else {
|
||||
holder.image.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
|
@ -180,9 +180,14 @@ public class StarredReposListAdapter extends RecyclerView.Adapter<StarredReposLi
|
||||
.endConfig()
|
||||
.buildRoundRect(firstCharacter, color, 3);
|
||||
|
||||
if (!currentItem.getAvatar_url().equals("")) {
|
||||
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
|
||||
} else {
|
||||
if (currentItem.getAvatar_url() != null) {
|
||||
if (!currentItem.getAvatar_url().equals("")) {
|
||||
Picasso.get().load(currentItem.getAvatar_url()).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.image);
|
||||
} else {
|
||||
holder.image.setImageDrawable(drawable);
|
||||
}
|
||||
}
|
||||
else {
|
||||
holder.image.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
|
225
app/src/main/java/org/mian/gitnex/fragments/FilesFragment.java
Normal file
@ -0,0 +1,225 @@
|
||||
package org.mian.gitnex.fragments;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import android.os.Handler;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.adapters.FilesAdapter;
|
||||
import org.mian.gitnex.helpers.Authorization;
|
||||
import org.mian.gitnex.models.Files;
|
||||
import org.mian.gitnex.util.AppUtil;
|
||||
import org.mian.gitnex.util.TinyDB;
|
||||
import org.mian.gitnex.viewmodels.FilesViewModel;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class FilesFragment extends Fragment {
|
||||
|
||||
private ProgressBar mProgressBar;
|
||||
private FilesAdapter adapter;
|
||||
private RecyclerView mRecyclerView;
|
||||
private TextView noDataFiles;
|
||||
private LinearLayout filesFrame;
|
||||
private static String repoNameF = "param2";
|
||||
private static String repoOwnerF = "param1";
|
||||
private boolean initialLoad = true;
|
||||
|
||||
private String repoName;
|
||||
private String repoOwner;
|
||||
|
||||
private OnFragmentInteractionListener mListener;
|
||||
|
||||
public FilesFragment() {
|
||||
}
|
||||
|
||||
public static FilesFragment newInstance(String param1, String param2) {
|
||||
FilesFragment fragment = new FilesFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(repoOwnerF, param1);
|
||||
args.putString(repoNameF, param2);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
repoName = getArguments().getString(repoNameF);
|
||||
repoOwner = getArguments().getString(repoOwnerF);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View v = inflater.inflate(R.layout.fragment_files, container, false);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
TinyDB tinyDb = new TinyDB(getContext());
|
||||
final String instanceUrl = tinyDb.getString("instanceUrl");
|
||||
final String loginUid = tinyDb.getString("loginUid");
|
||||
final String instanceToken = "token " + tinyDb.getString(loginUid + "-token");
|
||||
|
||||
noDataFiles = v.findViewById(R.id.noDataFiles);
|
||||
filesFrame = v.findViewById(R.id.filesFrame);
|
||||
|
||||
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
|
||||
|
||||
mRecyclerView = v.findViewById(R.id.recyclerView);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
||||
String filesDirDB = tinyDb.getString("filesDir");
|
||||
|
||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
|
||||
DividerItemDecoration.VERTICAL);
|
||||
mRecyclerView.addItemDecoration(dividerItemDecoration);
|
||||
|
||||
mProgressBar = v.findViewById(R.id.progress_bar);
|
||||
|
||||
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
swipeRefresh.setRefreshing(false);
|
||||
FilesViewModel.loadFilesList(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
fetchDataAsync(instanceUrl, Authorization.returnAuthentication(getContext(), loginUid, instanceToken), repoOwner, repoName);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
private void fetchDataAsync(String instanceUrl, String instanceToken, String owner, String repo) {
|
||||
|
||||
FilesViewModel filesModel = new ViewModelProvider(this).get(FilesViewModel.class);
|
||||
|
||||
filesModel.getFilesList(instanceUrl, instanceToken, owner, repo).observe(this, new Observer<List<Files>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<Files> filesListMain) {
|
||||
adapter = new FilesAdapter(getContext(), filesListMain);
|
||||
if(adapter.getItemCount() > 0) {
|
||||
mRecyclerView.setAdapter(adapter);
|
||||
filesFrame.setVisibility(View.VISIBLE);
|
||||
noDataFiles.setVisibility(View.GONE);
|
||||
}
|
||||
else {
|
||||
adapter.notifyDataSetChanged();
|
||||
mRecyclerView.setAdapter(adapter);
|
||||
filesFrame.setVisibility(View.VISIBLE);
|
||||
noDataFiles.setVisibility(View.VISIBLE);
|
||||
}
|
||||
filesFrame.setVisibility(View.VISIBLE);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void fetchDataAsyncSub(String instanceUrl, String instanceToken, String owner, String repo, String filesDir) {
|
||||
|
||||
FilesViewModel filesModel2 = new ViewModelProvider(this).get(FilesViewModel.class);
|
||||
|
||||
filesModel2.getFilesList2(instanceUrl, instanceToken, owner, repo, filesDir).observe(this, new Observer<List<Files>>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable List<Files> filesListMain2) {
|
||||
adapter = new FilesAdapter(getContext(), filesListMain2);
|
||||
if(adapter.getItemCount() > 0) {
|
||||
mRecyclerView.setAdapter(adapter);
|
||||
filesFrame.setVisibility(View.VISIBLE);
|
||||
noDataFiles.setVisibility(View.GONE);
|
||||
}
|
||||
else {
|
||||
adapter.notifyDataSetChanged();
|
||||
mRecyclerView.setAdapter(adapter);
|
||||
filesFrame.setVisibility(View.VISIBLE);
|
||||
noDataFiles.setVisibility(View.VISIBLE);
|
||||
}
|
||||
filesFrame.setVisibility(View.VISIBLE);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||
|
||||
boolean connToInternet = AppUtil.haveNetworkConnection(Objects.requireNonNull(getContext()));
|
||||
|
||||
inflater.inflate(R.menu.search_menu, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
androidx.appcompat.widget.SearchView searchView = (androidx.appcompat.widget.SearchView) searchItem.getActionView();
|
||||
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
searchView.setQueryHint(getContext().getString(R.string.strFilter));
|
||||
|
||||
if(!connToInternet) {
|
||||
return;
|
||||
}
|
||||
|
||||
searchView.setOnQueryTextListener(new androidx.appcompat.widget.SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
if(mRecyclerView.getAdapter() != null) {
|
||||
adapter.getFilter().filter(newText);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void onButtonPressed(Uri uri) {
|
||||
if (mListener != null) {
|
||||
mListener.onFragmentInteraction(uri);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
public interface OnFragmentInteractionListener {
|
||||
void onFragmentInteraction(Uri uri);
|
||||
}
|
||||
}
|
@ -247,7 +247,7 @@ public class RepoInfoFragment extends Fragment {
|
||||
repoRepoUrlInfo.setText(repoInfo.getHtml_url());
|
||||
repoForksCountInfo.setText(repoInfo.getForks_count());
|
||||
|
||||
if(repoInfo.getHas_issues()) {
|
||||
if(repoInfo.getHas_issues() != null) {
|
||||
tinyDb.putBoolean("hasIssues", repoInfo.getHas_issues());
|
||||
}
|
||||
else {
|
||||
|
@ -3,6 +3,7 @@ package org.mian.gitnex.interfaces;
|
||||
import com.google.gson.JsonElement;
|
||||
import org.mian.gitnex.models.AddEmail;
|
||||
import org.mian.gitnex.models.Branches;
|
||||
import org.mian.gitnex.models.Files;
|
||||
import org.mian.gitnex.models.NewFile;
|
||||
import org.mian.gitnex.models.UpdateIssueAssignee;
|
||||
import org.mian.gitnex.models.UpdateIssueState;
|
||||
@ -214,4 +215,13 @@ public interface ApiInterface {
|
||||
|
||||
@POST("repos/{owner}/{repo}/contents/{file}") // create new file
|
||||
Call<JsonElement> createNewFile(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("file") String fileName, @Body NewFile jsonStr);
|
||||
|
||||
@GET("repos/{owner}/{repo}/contents") // get all the files and dirs of a repository
|
||||
Call<List<Files>> getFiles(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName);
|
||||
|
||||
@GET("repos/{owner}/{repo}/contents/{file}") // get single file contents
|
||||
Call<Files> getSingleFileContents(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("file") String file);
|
||||
|
||||
@GET("repos/{owner}/{repo}/contents/{fileDir}") // get all the sub files and dirs of a repository
|
||||
Call<List<Files>> getDirFiles(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("fileDir") String fileDir);
|
||||
}
|
74
app/src/main/java/org/mian/gitnex/models/Files.java
Normal file
@ -0,0 +1,74 @@
|
||||
package org.mian.gitnex.models;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class Files {
|
||||
|
||||
private String name;
|
||||
private String path;
|
||||
private String sha;
|
||||
private String type;
|
||||
private int size;
|
||||
private String encoding;
|
||||
private String content;
|
||||
private String target;
|
||||
private String url;
|
||||
private String html_url;
|
||||
private String git_url;
|
||||
private String download_url;
|
||||
private String submodule_git_url;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getSha() {
|
||||
return sha;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getHtml_url() {
|
||||
return html_url;
|
||||
}
|
||||
|
||||
public String getGit_url() {
|
||||
return git_url;
|
||||
}
|
||||
|
||||
public String getDownload_url() {
|
||||
return download_url;
|
||||
}
|
||||
|
||||
public String getSubmodule_git_url() {
|
||||
return submodule_git_url;
|
||||
}
|
||||
}
|
112
app/src/main/java/org/mian/gitnex/viewmodels/FilesViewModel.java
Normal file
@ -0,0 +1,112 @@
|
||||
package org.mian.gitnex.viewmodels;
|
||||
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.models.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class FilesViewModel extends ViewModel {
|
||||
|
||||
private static MutableLiveData<List<Files>> filesList;
|
||||
private static MutableLiveData<List<Files>> filesList2;
|
||||
|
||||
public LiveData<List<Files>> getFilesList(String instanceUrl, String token, String owner, String repo) {
|
||||
|
||||
filesList = new MutableLiveData<>();
|
||||
loadFilesList(instanceUrl, token, owner, repo);
|
||||
|
||||
return filesList;
|
||||
}
|
||||
|
||||
public static void loadFilesList(String instanceUrl, String token, String owner, String repo) {
|
||||
|
||||
Call<List<Files>> call = RetrofitClient
|
||||
.getInstance(instanceUrl)
|
||||
.getApiInterface()
|
||||
.getFiles(token, owner, repo);
|
||||
|
||||
call.enqueue(new Callback<List<Files>>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<List<Files>> call, @NonNull Response<List<Files>> response) {
|
||||
|
||||
Collections.sort(response.body(), new Comparator<Files>() {
|
||||
@Override
|
||||
public int compare(Files byType1, Files byType2) {
|
||||
return byType1.getType().compareTo(byType2.getType());
|
||||
}
|
||||
});
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
filesList.postValue(response.body());
|
||||
} else {
|
||||
Log.i("onResponse", String.valueOf(response.code()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<List<Files>> call, Throwable t) {
|
||||
Log.i("onFailure", t.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public LiveData<List<Files>> getFilesList2(String instanceUrl, String token, String owner, String repo, String filesDir) {
|
||||
|
||||
filesList = new MutableLiveData<>();
|
||||
loadFilesList2(instanceUrl, token, owner, repo, filesDir);
|
||||
|
||||
return filesList;
|
||||
}
|
||||
|
||||
public static void loadFilesList2(String instanceUrl, String token, String owner, String repo, String filesDir) {
|
||||
|
||||
Call<List<Files>> call = RetrofitClient
|
||||
.getInstance(instanceUrl)
|
||||
.getApiInterface()
|
||||
.getDirFiles(token, owner, repo, filesDir);
|
||||
|
||||
call.enqueue(new Callback<List<Files>>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<List<Files>> call, @NonNull Response<List<Files>> response) {
|
||||
|
||||
Collections.sort(response.body(), new Comparator<Files>() {
|
||||
@Override
|
||||
public int compare(Files byType1, Files byType2) {
|
||||
return byType1.getType().compareTo(byType2.getType());
|
||||
}
|
||||
});
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
filesList.postValue(response.body());
|
||||
} else {
|
||||
Log.i("onResponse", String.valueOf(response.code()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<List<Files>> call, Throwable t) {
|
||||
Log.i("onFailure", t.toString());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
11
app/src/main/res/drawable/ic_file_new.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="512dp"
|
||||
android:height="512dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16"
|
||||
tools:ignore="VectorRaster">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m13.707,3.293 l-3,-3c-0.1875,-0.1875 -0.4419,-0.293 -0.707,-0.293h-7c-0.5522,0 -1,0.4478 -1,1v14c0,0.5527 0.4478,1 1,1h10c0.5522,0 1,-0.4473 1,-1v-11c0,-0.2651 -0.1055,-0.5195 -0.293,-0.707zM8,12h-3v-2h3zM11,9h-6v-2h6zM11,4c-0.5523,0 -1,-0.4478 -1,-1v-2l3,3z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_folder_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_question_mark_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
|
||||
</vector>
|
@ -4,8 +4,8 @@
|
||||
|
||||
<item
|
||||
android:id="@android:id/background"
|
||||
android:top="4dp"
|
||||
android:bottom="4dp"
|
||||
android:top="2dp"
|
||||
android:bottom="2dp"
|
||||
android:right="1dp"
|
||||
android:left="1dp">
|
||||
<shape>
|
||||
@ -16,12 +16,12 @@
|
||||
|
||||
<item
|
||||
android:id="@android:id/progress"
|
||||
android:top="1dp"
|
||||
android:bottom="1dp"
|
||||
android:top="3dp"
|
||||
android:bottom="3dp"
|
||||
android:left="1dp"
|
||||
android:right="1dp">
|
||||
|
||||
<scale android:scaleWidth="100%" android:scaleHeight="80%">
|
||||
<scale android:scaleWidth="100%">
|
||||
<shape>
|
||||
<corners android:radius="15dp" />
|
||||
</shape>
|
||||
|
78
app/src/main/res/layout/activity_file_view.xml
Normal file
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:background="@color/colorPrimary">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/close"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:gravity="center_vertical"
|
||||
android:contentDescription="@string/close"
|
||||
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="@color/white"
|
||||
android:maxLines="1"
|
||||
android:textSize="20sp" />
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_marginTop="50dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/toastBackground">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/singleFileContents"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="16sp"
|
||||
android:padding="15dp"
|
||||
/>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="@style/Base.Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true"
|
||||
android:visibility="visible" />
|
||||
|
||||
</RelativeLayout>
|
@ -22,7 +22,7 @@
|
||||
android:layout_marginBottom="20dp"
|
||||
android:baselineAligned="false"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:src="@mipmap/app_logo_round" />
|
||||
android:src="@mipmap/app_logo" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -39,6 +39,12 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/tab_text_info" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:id="@+id/tabItemFiles"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/tab_text_files" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:id="@+id/tabItem2_issues"
|
||||
android:layout_width="wrap_content"
|
||||
|
60
app/src/main/res/layout/files_list.xml
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/linearLayoutFilesFrame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="10dp"
|
||||
android:theme="@style/AppTheme"
|
||||
android:background="@color/backgroundColor"
|
||||
tools:context=".activities.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fileType"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fileImage"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:contentDescription="@string/repoContentAvatar"
|
||||
android:src="@drawable/ic_android" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/infoSection"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@+id/fileImage"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fileName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight=".80"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:text="@string/defaultFilename"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/filesDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight=".10"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:scaleType="fitEnd"
|
||||
android:visibility="gone"
|
||||
android:src="@drawable/ic_dotted_menu_horizontal"
|
||||
android:contentDescription="@string/menuContentDesc" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
@ -25,7 +25,7 @@
|
||||
android:layout_marginTop="20dp"
|
||||
android:baselineAligned="false"
|
||||
android:contentDescription="@string/logo"
|
||||
android:src="@mipmap/app_logo_round" />
|
||||
android:src="@mipmap/app_logo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/appName"
|
||||
|
68
app/src/main/res/layout/fragment_files.xml
Normal file
@ -0,0 +1,68 @@
|
||||
<?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"
|
||||
android:orientation="vertical"
|
||||
tools:context=".activities.RepoDetailActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/filesFrame"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fileBrowserBreadcrumb"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:textColor="@color/lightGray"
|
||||
android:text="@string/filesBreadcrumb" />
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/pullToRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorPrimary"
|
||||
android:padding="4dp"
|
||||
android:scrollbars="vertical"
|
||||
/>
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noDataFiles"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="15dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/noDataFilesTab"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="@style/Base.Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
@ -67,7 +67,7 @@
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="82"
|
||||
android:layout_weight="80"
|
||||
android:progress="50"
|
||||
android:layout_marginTop="2dp"
|
||||
android:progressDrawable="@drawable/progress_bar"
|
||||
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 12 KiB |
@ -114,6 +114,7 @@
|
||||
<string name="infoTabRepoForksCount">Anzahl an Forks</string>
|
||||
<string name="infoTabRepoCreatedAt">Erstellt</string>
|
||||
<string name="infoTabRepoUpdatedAt">Letzte Aktualisierung</string>
|
||||
|
||||
<string name="timeAtText">um</string>
|
||||
<string name="createdText">Erstellt\u0020</string>
|
||||
<string name="dueDateText">Fälligkeitsdatum </string>
|
||||
@ -135,6 +136,7 @@
|
||||
<string name="commentSuccess">Kommentar gepostet</string>
|
||||
<string name="commentError">Etwas ist schief gelaufen. Bitte versuche es erneut</string>
|
||||
<string name="generalImgContentText">Benutzerbild</string>
|
||||
|
||||
<string name="noDataMilestonesTab">Kein Meilenstein gefunden!</string>
|
||||
<string name="commitAuthor">Commit Autor: %1$s</string>
|
||||
<string name="commitHash">Commit Hash \n%1$s%2$s</string>
|
||||
@ -370,11 +372,16 @@
|
||||
<string name="copyIssueUrl">Issue Link kopieren</string>
|
||||
<string name="copyIssueUrlToastMsg">Issue Link in Zwischenablage kopiert</string>
|
||||
<string name="milestoneCompletion">%1$d\uFF05 abgeschlossen</string>
|
||||
|
||||
<!-- files -->
|
||||
<string name="noDataFilesTab">Keine Dateien gefunden</string>
|
||||
|
||||
<!-- files -->
|
||||
<string name="noDataFilesTab">Keine Dateien gefunden</string>
|
||||
<string name="filesDirNotSupportedYet">Ordner sind noch nicht unterstützt</string>
|
||||
<string name="filesGenericError">Datei kann nicht angezeigt werden, da die API einen Fehler meldet</string>
|
||||
<string name="filesBreadcrumb">Wurzel</string>
|
||||
|
||||
<!-- generic copy -->
|
||||
<string name="okButton">OK</string>
|
||||
<string name="doneButton">Fertig</string>
|
||||
|
@ -114,6 +114,8 @@
|
||||
<string name="infoTabRepoForksCount">Forks Count</string>
|
||||
<string name="infoTabRepoCreatedAt">Created</string>
|
||||
<string name="infoTabRepoUpdatedAt">Last Updated</string>
|
||||
<string name="infoTabRepoDefaultBranchText">master</string>
|
||||
|
||||
<string name="timeAtText">à</string>
|
||||
<string name="createdText">Created\u0020</string>
|
||||
<string name="dueDateText">Due Date</string>
|
||||
@ -135,6 +137,7 @@
|
||||
<string name="commentSuccess">Comment posted</string>
|
||||
<string name="commentError">Something went wrong, please try again</string>
|
||||
<string name="generalImgContentText">IMG</string>
|
||||
|
||||
<string name="noDataMilestonesTab">No Milestone found!</string>
|
||||
<string name="commitAuthor">Commit author : %1$s</string>
|
||||
<string name="commitHash">Commit hash \n%1$s%2$s</string>
|
||||
@ -370,11 +373,16 @@
|
||||
<string name="copyIssueUrl">Copier l Issue URL</string>
|
||||
<string name="copyIssueUrlToastMsg">Issue URL copied to clipboard</string>
|
||||
<string name="milestoneCompletion">%1$d\uFF05 terminé</string>
|
||||
|
||||
<!-- files -->
|
||||
<string name="noDataFilesTab">Aucun fichier trouvé</string>
|
||||
|
||||
<!-- files -->
|
||||
<string name="noDataFilesTab">Aucun fichier trouvé</string>
|
||||
<string name="filesDirNotSupportedYet">Directory browsing is not supported yet</string>
|
||||
<string name="filesGenericError">Sorry this file cannot be viewed as API returned an error</string>
|
||||
<string name="filesBreadcrumb">Root</string>
|
||||
|
||||
<!-- generic copy -->
|
||||
<string name="okButton">OK</string>
|
||||
<string name="doneButton">Done</string>
|
||||
|
@ -114,6 +114,8 @@
|
||||
<string name="infoTabRepoForksCount">Кол-во форков</string>
|
||||
<string name="infoTabRepoCreatedAt">Создан</string>
|
||||
<string name="infoTabRepoUpdatedAt">Последнее обновление</string>
|
||||
<string name="infoTabRepoDefaultBranchText">master</string>
|
||||
|
||||
<string name="timeAtText">в</string>
|
||||
<string name="createdText">Создано\u0020</string>
|
||||
<string name="dueDateText">Дата исполнения</string>
|
||||
@ -135,6 +137,7 @@
|
||||
<string name="commentSuccess">Комментарий отправлен!</string>
|
||||
<string name="commentError">Что-то пошло не так. Пожалуйста, попытайтесь еще раз.</string>
|
||||
<string name="generalImgContentText">Аватар</string>
|
||||
|
||||
<string name="noDataMilestonesTab">Вех не обнаружено</string>
|
||||
<string name="commitAuthor">Автор коммита: %1$s</string>
|
||||
<string name="commitHash">Хеш коммита \n%1$s%2$s</string>
|
||||
@ -370,11 +373,16 @@
|
||||
<string name="copyIssueUrl">Copy Issue URL</string>
|
||||
<string name="copyIssueUrlToastMsg">Issue URL copied to clipboard</string>
|
||||
<string name="milestoneCompletion">%1$d\uFF05 выполненный</string>
|
||||
|
||||
<!-- files -->
|
||||
<string name="noDataFilesTab">Файлов не найдено</string>
|
||||
|
||||
<!-- files -->
|
||||
<string name="noDataFilesTab">Файлов не найдено</string>
|
||||
<string name="filesDirNotSupportedYet">Directory browsing is not supported yet</string>
|
||||
<string name="filesGenericError">Sorry this file cannot be viewed as API returned an error</string>
|
||||
<string name="filesBreadcrumb">Root</string>
|
||||
|
||||
<!-- generic copy -->
|
||||
<string name="okButton">OK</string>
|
||||
<string name="doneButton">Готово</string>
|
||||
|
@ -1,10 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Generated by crowdin.com-->
|
||||
<resources>
|
||||
<!-- These strings does not need translations -->
|
||||
<!-- These strings does not need translations -->
|
||||
<!-- links text -->
|
||||
<!-- links text -->
|
||||
<!-- menu items -->
|
||||
<string name="navMyRepos">我的仓库</string>
|
||||
<string name="navStarredRepos">已点赞</string>
|
||||
@ -66,7 +62,6 @@
|
||||
<string name="logo">Login to Gitea</string>
|
||||
<string name="urlInfoTooltip">1- Choose the correct protocol(https or http). \n2- Enter Gitea url e.g: try.gitea.io. \n3- If you have enabled 2FA for your account, enter the code in the OTP Code field. \n4- For HTTP basic auth use USERNAME@DOMAIN.COM in the URL field.</string>
|
||||
<string name="loginFailed">Wrong username/password</string>
|
||||
<string name="protocolDelimiter">://</string>
|
||||
<string name="protocolError">It is not recommended to use HTTP protocol unless you are testing on local network.</string>
|
||||
<string name="malformedJson">Malformed JSON was received. Server response was not successful.</string>
|
||||
<string name="emptyFieldURL">Instance URL is required</string>
|
||||
@ -93,13 +88,11 @@
|
||||
<string name="orgContentAvatar">Org</string>
|
||||
<string name="repoContentAvatar">Repo</string>
|
||||
<string name="privateAvatar">Pri</string>
|
||||
<string name="repoStars">12345</string>
|
||||
<string name="repoWatchers">98324</string>
|
||||
<string name="repoIssues">54321</string>
|
||||
<string name="removeContent">Remove</string>
|
||||
<string name="genericApiStatusError">Instance has returned an error. Code\u0020</string>
|
||||
<string name="title_activity_repo_detail">RepoDetailActivity</string>
|
||||
<string name="tab_text_info">Details</string>
|
||||
<string name="tab_text_files">Files</string>
|
||||
<string name="tab_text_issues">Open Issues</string>
|
||||
<string name="tabItemCloseIssues">Closed Issues</string>
|
||||
<string name="tab_text_ml">Milestones</string>
|
||||
@ -121,12 +114,7 @@
|
||||
<string name="infoTabRepoForksCount">Forks</string>
|
||||
<string name="infoTabRepoCreatedAt">Created</string>
|
||||
<string name="infoTabRepoUpdatedAt">Last Updated</string>
|
||||
<string name="infoTabRepoDummyTime">2018–10–30 08:25:25</string>
|
||||
<string name="infoTabRepoBlank">…</string>
|
||||
<string name="infoTabRepoZero">0</string>
|
||||
<string name="infoTabRepoDefaultBranchText">master</string>
|
||||
<string name="timeAtText">at</string>
|
||||
<string name="hash">#</string>
|
||||
<string name="createdText">Opened\u0020</string>
|
||||
<string name="dueDateText">Due Date</string>
|
||||
<string name="issueStatusTextOpen">Status: open</string>
|
||||
@ -138,7 +126,6 @@
|
||||
<string name="issueTypeIssue">Type: Issue</string>
|
||||
<string name="issueTypePullRequest">Type: Pull Request</string>
|
||||
<string name="issueCommenter">Commenter:\u0020</string>
|
||||
<string name="issueTitleWithId">#%1$d %2$s</string>
|
||||
<string name="issueMilestone">Milestone %1$s</string>
|
||||
<string name="dueDate">Due %1$s</string>
|
||||
<string name="createdTime">Opened %1$s</string>
|
||||
@ -148,7 +135,6 @@
|
||||
<string name="commentSuccess">Comment posted</string>
|
||||
<string name="commentError">Something went wrong, please try again</string>
|
||||
<string name="generalImgContentText">Avatar</string>
|
||||
<string name="generalPageTitle">GitNex</string>
|
||||
<string name="noDataMilestonesTab">No milestones found</string>
|
||||
<string name="commitAuthor">Commit author: %1$s</string>
|
||||
<string name="commitHash">Commit hash \n%1$s%2$s</string>
|
||||
@ -166,7 +152,6 @@
|
||||
<string name="newMilestoneTitle">Title</string>
|
||||
<string name="newMilestoneDescription">Description</string>
|
||||
<string name="newMilestoneDueDate">Due Date</string>
|
||||
<string name="setDueDate">%1$d-%2$d-%3$d</string>
|
||||
<string name="milestoneNameErrorEmpty">Milestone title is empty</string>
|
||||
<string name="milestoneNameErrorInvalid">Milestone title is not valid. [a–z A–Z 0–9 – _]</string>
|
||||
<string name="milestoneDescError">Milestone description exceeds the max 255 characters limit</string>
|
||||
@ -185,8 +170,6 @@
|
||||
<string name="newIssueDueDateTitle">Due Date</string>
|
||||
<string name="newIssueMilestoneTitle">Milestone</string>
|
||||
<string name="newIssueLabelsTitle">Labels</string>
|
||||
<string name="spinnerMilestoneText">%1$s [%2$s]</string>
|
||||
<string name="dialogAssignessText">%1$s - @%2$s</string>
|
||||
<string name="issueTitleEmpty">Issue title is empty</string>
|
||||
<string name="issueDescriptionEmpty">Issue description is empty</string>
|
||||
<string name="issueCreated">New issue created successfully</string>
|
||||
@ -211,15 +194,15 @@
|
||||
<string name="settingsHomeScreenSelectedText">My Repositories</string>
|
||||
<string name="settingshomeScreenSelectorDialogTitle">Select Home Screen</string>
|
||||
<!-- settings -->
|
||||
<string name="noMoreData">No more data available.</string>
|
||||
<string name="noMoreData">No more data available</string>
|
||||
<string name="createLabel">New Label</string>
|
||||
<string name="menuTitleText">Repo Menu</string>
|
||||
<string name="labelName">Label Name</string>
|
||||
<string name="labelColor">Label Color</string>
|
||||
<string name="labelEmptyError">Label name is empty.</string>
|
||||
<string name="labelNameError">Label name is not valid.</string>
|
||||
<string name="labelEmptyError">Label name is empty</string>
|
||||
<string name="labelNameError">Label name is not valid</string>
|
||||
<string name="labelCreated">Label created.</string>
|
||||
<string name="labelGeneralError">Something went wrong, please try again.</string>
|
||||
<string name="labelGeneralError">Something went wrong, please try again</string>
|
||||
<string name="labelUpdated">Label updated.</string>
|
||||
<string name="noDataLabelsTab">No labels found</string>
|
||||
<string name="labelMenuContentDesc">Desc</string>
|
||||
@ -232,7 +215,7 @@
|
||||
<!-- credits - this part does not need translation -->
|
||||
<!-- credits - this part does not need translation -->
|
||||
<string name="alertDialogTokenRevokedTitle">Authorization Error</string>
|
||||
<string name="alertDialogTokenRevokedMessage">It seems that the Access Token is revoked OR your are not allowed to see these contents. In case of revoked Token, please logout and login again.</string>
|
||||
<string name="alertDialogTokenRevokedMessage">It seems that the Access Token is revoked OR your are not allowed to see these contents. In case of revoked Token, please logout and login again</string>
|
||||
<string name="alertDialogTokenRevokedCopyNegativeButton">Cancel</string>
|
||||
<string name="alertDialogTokenRevokedCopyPositiveButton">Logout</string>
|
||||
<string name="labelDeleteTitle">Delete\u0020</string>
|
||||
@ -258,16 +241,16 @@
|
||||
<string name="newTeamDesc">Description</string>
|
||||
<string name="newTeamPermission">Permission</string>
|
||||
<string name="newTeamAccessControls">Access Controls</string>
|
||||
<string name="newTeamPermissionRead">Members can view and clone team repositories.</string>
|
||||
<string name="newTeamPermissionWrite">Members can read and push to team repositories.</string>
|
||||
<string name="newTeamPermissionAdmin">Members can pull and push to team repositories and add collaborators to them.</string>
|
||||
<string name="teamNameEmpty">Please enter team name.</string>
|
||||
<string name="teamNameError">Team name should contain only alphanumeric, dash (-), underscore (_) and dot (.) characters.</string>
|
||||
<string name="teamPermissionEmpty">Please select permission.</string>
|
||||
<string name="teamDescError">Team description have illegal characters.</string>
|
||||
<string name="teamDescLimit">Team description have more than 100 characters.</string>
|
||||
<string name="teamCreated">Team created successfully.</string>
|
||||
<string name="teamCreatedError">Something went wrong, please try again.</string>
|
||||
<string name="newTeamPermissionRead">Members can view and clone team repositories</string>
|
||||
<string name="newTeamPermissionWrite">Members can read and push to team repositories</string>
|
||||
<string name="newTeamPermissionAdmin">Members can pull and push to team repositories and add collaborators to them</string>
|
||||
<string name="teamNameEmpty">Please enter team name</string>
|
||||
<string name="teamNameError">Team name should contain only alphanumeric, dash (-), underscore (_) and dot (.) characters</string>
|
||||
<string name="teamPermissionEmpty">Please select permission</string>
|
||||
<string name="teamDescError">Team description have illegal characters</string>
|
||||
<string name="teamDescLimit">Team description have more than 100 characters</string>
|
||||
<string name="teamCreated">Team created successfully</string>
|
||||
<string name="teamCreatedError">Something went wrong, please try again</string>
|
||||
<!-- create team -->
|
||||
<!-- edit comment -->
|
||||
<string name="editCommentTitle">Edit Comment</string>
|
||||
@ -291,8 +274,8 @@
|
||||
<string name="profileEmailTitle">Email Address</string>
|
||||
<string name="emailAddedText">New email added successfully.</string>
|
||||
<string name="emailErrorEmpty">Email address is empty.</string>
|
||||
<string name="emailErrorInvalid">Email address is not valid.</string>
|
||||
<string name="emailErrorInUse">Email address is already in use.</string>
|
||||
<string name="emailErrorInvalid">Email address is not valid</string>
|
||||
<string name="emailErrorInUse">Email address is already in use</string>
|
||||
<string name="emailTypeText">Primary</string>
|
||||
<string name="profileTabEmails">Emails</string>
|
||||
<!-- profile section -->
|
||||
@ -387,6 +370,11 @@
|
||||
<string name="copyIssueUrl">Copy Issue URL</string>
|
||||
<string name="copyIssueUrlToastMsg">Issue URL copied to clipboard</string>
|
||||
<string name="milestoneCompletion">%1$d\uFF05 completed</string>
|
||||
<!-- files -->
|
||||
<string name="noDataFilesTab">No files found</string>
|
||||
<string name="filesDirNotSupportedYet">Directory browsing is not supported yet</string>
|
||||
<string name="filesGenericError">Sorry this file cannot be viewed as API returned an error</string>
|
||||
<string name="filesBreadcrumb">Root</string>
|
||||
<!-- generic copy -->
|
||||
<string name="okButton">OK</string>
|
||||
<string name="doneButton">Done</string>
|
||||
@ -408,6 +396,5 @@
|
||||
<string name="locationText">Location</string>
|
||||
<string name="characters255Limit">Max 255 characters</string>
|
||||
<string name="emptyFields">All fields are required</string>
|
||||
<string name="translateText">Translate GitNex with Crowdin</string>
|
||||
<!-- generic copy -->
|
||||
</resources>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<!-- These strings does not need translations -->
|
||||
|
||||
<string name="app_name" translatable="false">GitNex</string>
|
||||
<string name="appAuthor" translatable="false">Developer : M M Arif</string>
|
||||
<string name="appEmail" translatable="false">gitnex@gitnex.com</string>
|
||||
@ -14,14 +14,10 @@
|
||||
<string name="supportLinkPatreon" translatable="false">https://www.patreon.com/mmarif</string>
|
||||
<string name="appVerBuild" translatable="false">%1$s / build %2$d</string>
|
||||
<string name="appDesc" translatable="false">GitNex is a free, open-source Android client for Git repository management tool Gitea. GitNex is Licensed under GPLv3.\n\nThanks to all the contributors and sponsors for your generous work and donations.</string>
|
||||
<string name="corwdinLink" translatable="false">https://crowdin.com/project/gitnex</string>
|
||||
<!-- These strings does not need translations -->
|
||||
|
||||
<!-- links text -->
|
||||
<string name="appRepoIssuesText" translatable="false">Report issues at Gitea</string>
|
||||
<string name="supportText" translatable="false">Support the App on Liberapay</string>
|
||||
<string name="supportTextPatreon" translatable="false">Become a Patreon</string>
|
||||
<!-- links text -->
|
||||
|
||||
<!-- menu items -->
|
||||
<string name="navMyRepos">My Repositories</string>
|
||||
@ -92,7 +88,7 @@
|
||||
<string name="logo">Login to Gitea</string>
|
||||
<string name="urlInfoTooltip">1- Choose the correct protocol(https or http). \n2- Enter Gitea url e.g: try.gitea.io. \n3- If you have enabled 2FA for your account, enter the code in the OTP Code field. \n4- For HTTP basic auth use USERNAME@DOMAIN.COM in the URL field.</string>
|
||||
<string name="loginFailed">Wrong username/password</string>
|
||||
<string name="protocolDelimiter">://</string>
|
||||
<string name="protocolDelimiter" translatable="false">://</string>
|
||||
<string name="protocolError">It is not recommended to use HTTP protocol unless you are testing on local network.</string>
|
||||
<string name="malformedJson">Malformed JSON was received. Server response was not successful.</string>
|
||||
<string name="emptyFieldURL">Instance URL is required</string>
|
||||
@ -124,14 +120,15 @@
|
||||
<string name="orgContentAvatar">Org</string>
|
||||
<string name="repoContentAvatar">Repo</string>
|
||||
<string name="privateAvatar">Pri</string>
|
||||
<string name="repoStars">12345</string>
|
||||
<string name="repoWatchers">98324</string>
|
||||
<string name="repoIssues">54321</string>
|
||||
<string name="repoStars" translatable="false">12345</string>
|
||||
<string name="repoWatchers" translatable="false">98324</string>
|
||||
<string name="repoIssues" translatable="false">54321</string>
|
||||
<string name="removeContent">Remove</string>
|
||||
|
||||
<string name="genericApiStatusError">Instance has returned an error. Code\u0020</string>
|
||||
<string name="title_activity_repo_detail">RepoDetailActivity</string>
|
||||
<string name="tab_text_info">Details</string>
|
||||
<string name="tab_text_files">Files</string>
|
||||
<string name="tab_text_issues">Open Issues</string>
|
||||
<string name="tabItemCloseIssues">Closed Issues</string>
|
||||
<string name="tab_text_ml">Milestones</string>
|
||||
@ -155,13 +152,13 @@
|
||||
<string name="infoTabRepoForksCount">Forks</string>
|
||||
<string name="infoTabRepoCreatedAt">Created</string>
|
||||
<string name="infoTabRepoUpdatedAt">Last Updated</string>
|
||||
<string name="infoTabRepoDummyTime">2018–10–30 08:25:25</string>
|
||||
<string name="infoTabRepoBlank">…</string>
|
||||
<string name="infoTabRepoZero">0</string>
|
||||
<string name="infoTabRepoDefaultBranchText">master</string>
|
||||
<string name="infoTabRepoDummyTime" translatable="false">2018–10–30 08:25:25</string>
|
||||
<string name="infoTabRepoBlank" translatable="false">…</string>
|
||||
<string name="infoTabRepoZero" translatable="false">0</string>
|
||||
<string name="infoTabRepoDefaultBranchText" translatable="false">master</string>
|
||||
|
||||
<string name="timeAtText">at</string>
|
||||
<string name="hash">#</string>
|
||||
<string name="hash" translatable="false">#</string>
|
||||
<string name="createdText">Opened\u0020</string>
|
||||
<string name="dueDateText">Due Date</string>
|
||||
<string name="issueStatusTextOpen">Status: open</string>
|
||||
@ -173,7 +170,7 @@
|
||||
<string name="issueTypeIssue">Type: Issue</string>
|
||||
<string name="issueTypePullRequest">Type: Pull Request</string>
|
||||
<string name="issueCommenter">Commenter:\u0020</string>
|
||||
<string name="issueTitleWithId">#%1$d %2$s</string>
|
||||
<string name="issueTitleWithId" translatable="false">#%1$d %2$s</string>
|
||||
<string name="issueMilestone">Milestone %1$s</string>
|
||||
<string name="dueDate">Due %1$s</string>
|
||||
<string name="createdTime">Opened %1$s</string>
|
||||
@ -184,7 +181,7 @@
|
||||
<string name="commentError">Something went wrong, please try again</string>
|
||||
|
||||
<string name="generalImgContentText">Avatar</string>
|
||||
<string name="generalPageTitle">GitNex</string>
|
||||
<string name="generalPageTitle" translatable="false">GitNex</string>
|
||||
|
||||
<string name="noDataMilestonesTab">No milestones found</string>
|
||||
|
||||
@ -210,7 +207,7 @@
|
||||
<string name="newMilestoneTitle">Title</string>
|
||||
<string name="newMilestoneDescription">Description</string>
|
||||
<string name="newMilestoneDueDate">Due Date</string>
|
||||
<string name="setDueDate">%1$d-%2$d-%3$d</string>
|
||||
<string name="setDueDate" translatable="false">%1$d-%2$d-%3$d</string>
|
||||
<string name="milestoneNameErrorEmpty">Milestone title is empty</string>
|
||||
<string name="milestoneNameErrorInvalid">Milestone title is not valid. [a–z A–Z 0–9 – _]</string>
|
||||
<string name="milestoneDescError">Milestone description exceeds the max 255 characters limit</string>
|
||||
@ -230,8 +227,8 @@
|
||||
<string name="newIssueDueDateTitle">Due Date</string>
|
||||
<string name="newIssueMilestoneTitle">Milestone</string>
|
||||
<string name="newIssueLabelsTitle">Labels</string>
|
||||
<string name="spinnerMilestoneText">%1$s [%2$s]</string>
|
||||
<string name="dialogAssignessText">%1$s - @%2$s</string>
|
||||
<string name="spinnerMilestoneText" translatable="false">%1$s [%2$s]</string>
|
||||
<string name="dialogAssignessText" translatable="false">%1$s - @%2$s</string>
|
||||
<string name="issueTitleEmpty">Issue title is empty</string>
|
||||
<string name="issueDescriptionEmpty">Issue description is empty</string>
|
||||
<string name="issueCreated">New issue created successfully</string>
|
||||
@ -259,16 +256,16 @@
|
||||
<string name="settingshomeScreenSelectorDialogTitle">Select Home Screen</string>
|
||||
<!-- settings -->
|
||||
|
||||
<string name="noMoreData">No more data available.</string>
|
||||
<string name="noMoreData">No more data available</string>
|
||||
|
||||
<string name="createLabel">New Label</string>
|
||||
<string name="menuTitleText">Repo Menu</string>
|
||||
<string name="labelName">Label Name</string>
|
||||
<string name="labelColor">Label Color</string>
|
||||
<string name="labelEmptyError">Label name is empty.</string>
|
||||
<string name="labelNameError">Label name is not valid.</string>
|
||||
<string name="labelEmptyError">Label name is empty</string>
|
||||
<string name="labelNameError">Label name is not valid</string>
|
||||
<string name="labelCreated">Label created.</string>
|
||||
<string name="labelGeneralError">Something went wrong, please try again.</string>
|
||||
<string name="labelGeneralError">Something went wrong, please try again</string>
|
||||
<string name="labelUpdated">Label updated.</string>
|
||||
|
||||
<string name="noDataLabelsTab">No labels found</string>
|
||||
@ -287,7 +284,7 @@
|
||||
<!-- credits - this part does not need translation -->
|
||||
|
||||
<string name="alertDialogTokenRevokedTitle">Authorization Error</string>
|
||||
<string name="alertDialogTokenRevokedMessage">It seems that the Access Token is revoked OR your are not allowed to see these contents. In case of revoked Token, please logout and login again.</string>
|
||||
<string name="alertDialogTokenRevokedMessage">It seems that the Access Token is revoked OR your are not allowed to see these contents. In case of revoked Token, please logout and login again</string>
|
||||
<string name="alertDialogTokenRevokedCopyNegativeButton">Cancel</string>
|
||||
<string name="alertDialogTokenRevokedCopyPositiveButton">Logout</string>
|
||||
<string name="labelDeleteTitle">Delete\u0020</string>
|
||||
@ -315,18 +312,18 @@
|
||||
<string name="newTeamDesc">Description</string>
|
||||
<string name="newTeamPermission">Permission</string>
|
||||
<string name="newTeamAccessControls">Access Controls</string>
|
||||
<string name="newTeamPermissionRead">Members can view and clone team repositories.</string>
|
||||
<string name="newTeamPermissionWrite">Members can read and push to team repositories.</string>
|
||||
<string name="newTeamPermissionAdmin">Members can pull and push to team repositories and add collaborators to them.</string>
|
||||
<string name="newTeamPermissionRead">Members can view and clone team repositories</string>
|
||||
<string name="newTeamPermissionWrite">Members can read and push to team repositories</string>
|
||||
<string name="newTeamPermissionAdmin">Members can pull and push to team repositories and add collaborators to them</string>
|
||||
<string name="newTeamPermissionValues" translatable="false">%1$s%2$s,\u0020</string>
|
||||
<string name="newTeamPermissionValuesFinal" translatable="false">%1$s%2$s,\u0020</string>
|
||||
<string name="teamNameEmpty">Please enter team name.</string>
|
||||
<string name="teamNameError">Team name should contain only alphanumeric, dash (-), underscore (_) and dot (.) characters.</string>
|
||||
<string name="teamPermissionEmpty">Please select permission.</string>
|
||||
<string name="teamDescError">Team description have illegal characters.</string>
|
||||
<string name="teamDescLimit">Team description have more than 100 characters.</string>
|
||||
<string name="teamCreated">Team created successfully.</string>
|
||||
<string name="teamCreatedError">Something went wrong, please try again.</string>
|
||||
<string name="teamNameEmpty">Please enter team name</string>
|
||||
<string name="teamNameError">Team name should contain only alphanumeric, dash (-), underscore (_) and dot (.) characters</string>
|
||||
<string name="teamPermissionEmpty">Please select permission</string>
|
||||
<string name="teamDescError">Team description have illegal characters</string>
|
||||
<string name="teamDescLimit">Team description have more than 100 characters</string>
|
||||
<string name="teamCreated">Team created successfully</string>
|
||||
<string name="teamCreatedError">Something went wrong, please try again</string>
|
||||
<!-- create team -->
|
||||
|
||||
<!-- edit comment -->
|
||||
@ -353,8 +350,8 @@
|
||||
<string name="profileEmailTitle">Email Address</string>
|
||||
<string name="emailAddedText">New email added successfully.</string>
|
||||
<string name="emailErrorEmpty">Email address is empty.</string>
|
||||
<string name="emailErrorInvalid">Email address is not valid.</string>
|
||||
<string name="emailErrorInUse">Email address is already in use.</string>
|
||||
<string name="emailErrorInvalid">Email address is not valid</string>
|
||||
<string name="emailErrorInUse">Email address is already in use</string>
|
||||
<string name="emailTypeText">Primary</string>
|
||||
<string name="profileTabEmails">Emails</string>
|
||||
<string name="usernameWithAt" translatable="false">\u0040\u0020%1$s</string>
|
||||
@ -470,6 +467,12 @@
|
||||
|
||||
<string name="milestoneCompletion">%1$d\uFF05 completed</string>
|
||||
|
||||
<!-- files -->
|
||||
<string name="noDataFilesTab">No files found</string>
|
||||
<string name="filesDirNotSupportedYet">Directory browsing is not supported yet</string>
|
||||
<string name="filesGenericError">Sorry this file cannot be viewed as API returned an error</string>
|
||||
<string name="filesBreadcrumb">Root</string>
|
||||
|
||||
<!-- generic copy -->
|
||||
<string name="okButton">OK</string>
|
||||
<string name="doneButton">Done</string>
|
||||
@ -494,7 +497,6 @@
|
||||
<string name="locationText">Location</string>
|
||||
<string name="characters255Limit">Max 255 characters</string>
|
||||
<string name="emptyFields">All fields are required</string>
|
||||
<string name="translateText">Translate GitNex with Crowdin</string>
|
||||
<!-- generic copy -->
|
||||
|
||||
</resources>
|
||||
|
@ -7,7 +7,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||
|
||||
}
|
||||
}
|
||||
|
6
fastlane/metadata/android/en-US/changelogs/61.txt
Normal file
@ -0,0 +1,6 @@
|
||||
Bugfix: crash when repo avatar in not present in api nodes. old Gitea instances
|
||||
Bugfix: Milestone progress bar fix
|
||||
Bugfix: Create new issue enable/disable fix
|
||||
|
||||
For more, check the release notes.
|
||||
https://gitea.com/mmarif/GitNex/releases
|
4
fastlane/metadata/android/en-US/changelogs/62.txt
Normal file
@ -0,0 +1,4 @@
|
||||
Bugfix: crash when my repo, starred repos are accessed without repo avatar. old Gitea instances
|
||||
|
||||
For more, check the release notes.
|
||||
https://gitea.com/mmarif/GitNex/releases
|
13
fastlane/metadata/android/en-US/changelogs/63.txt
Normal file
@ -0,0 +1,13 @@
|
||||
2.1.3
|
||||
Bugfix: another old Gitea instances API issue
|
||||
|
||||
2.1.0
|
||||
- New: Font - Roboto
|
||||
- New: Milestone progress bar @6543
|
||||
- New: Redesign issues list
|
||||
- New: Copy issue URL to clipboard @6543
|
||||
- New: Redesign milestones list
|
||||
- New: Added repository avatars
|
||||
|
||||
For more, check the release notes.
|
||||
https://gitea.com/mmarif/GitNex/releases
|