mirror of
https://github.com/gitnex-org/gitnex.git
synced 2026-03-11 17:34:09 -05:00
Frontport and updates (#1429)
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1429 Co-authored-by: M M Arif <mmarif@swatian.com> Co-committed-by: M M Arif <mmarif@swatian.com>
This commit is contained in:
@@ -8,8 +8,8 @@ android {
|
||||
applicationId "org.mian.gitnex"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 35
|
||||
versionCode 800
|
||||
versionName "8.0.0"
|
||||
versionCode 895
|
||||
versionName "9.0.0-dev"
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
compileSdk 35
|
||||
@@ -34,6 +34,9 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
dependenciesInfo {
|
||||
includeInApk = false
|
||||
}
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
|
||||
@@ -96,7 +99,6 @@ dependencies {
|
||||
implementation "com.caverock:androidsvg-aar:1.4"
|
||||
implementation "pl.droidsonroids.gif:android-gif-drawable:1.2.29"
|
||||
implementation 'com.google.guava:guava:32.1.3-jre'
|
||||
implementation "com.github.HamidrezaAmz:BreadcrumbsView:0.2.9"
|
||||
//noinspection GradleDependency
|
||||
implementation 'commons-io:commons-io:2.5'
|
||||
implementation 'org.apache.commons:commons-lang3:3.13.0'
|
||||
|
||||
@@ -169,6 +169,7 @@ public class IssueDetailActivity extends BaseActivity
|
||||
private final float buttonAlphaStatEnabled = 1F;
|
||||
private int loadingFinished = 0;
|
||||
private MentionHelper mentionHelper;
|
||||
private boolean pullRequestFetchAttempted = false;
|
||||
|
||||
private enum Mode {
|
||||
EDIT,
|
||||
@@ -394,6 +395,7 @@ public class IssueDetailActivity extends BaseActivity
|
||||
getSingleIssue(repoOwner, repoName, issueIndex);
|
||||
getAttachments();
|
||||
fetchDataAsync(repoOwner, repoName, issueIndex);
|
||||
getPullRequest();
|
||||
|
||||
viewBinding.statuses.setOnClickListener(
|
||||
view -> {
|
||||
@@ -1016,7 +1018,7 @@ public class IssueDetailActivity extends BaseActivity
|
||||
if (issue.hasIssue()) {
|
||||
viewBinding.progressBar.setVisibility(View.GONE);
|
||||
getSubscribed();
|
||||
initWithIssue();
|
||||
checkAndInitWithIssue();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1037,9 +1039,9 @@ public class IssueDetailActivity extends BaseActivity
|
||||
|
||||
Issue singleIssue = response.body();
|
||||
assert singleIssue != null;
|
||||
|
||||
issue.setIssue(singleIssue);
|
||||
initWithIssue();
|
||||
loadingFinishedIssue = true;
|
||||
checkAndInitWithIssue();
|
||||
} else if (response.code() == 401) {
|
||||
|
||||
AlertDialogs.authorizationTokenRevokedDialog(ctx);
|
||||
@@ -1054,6 +1056,8 @@ public class IssueDetailActivity extends BaseActivity
|
||||
public void onFailure(@NonNull Call<Issue> call, @NonNull Throwable t) {
|
||||
|
||||
viewBinding.progressBar.setVisibility(View.GONE);
|
||||
loadingFinishedIssue = true;
|
||||
checkAndInitWithIssue();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1100,26 +1104,34 @@ public class IssueDetailActivity extends BaseActivity
|
||||
|
||||
viewBinding.issuePrState.setVisibility(View.VISIBLE);
|
||||
|
||||
if (issue.getIssue() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (issue.getIssue().getPullRequest() != null) {
|
||||
|
||||
viewBinding.statusesLvMain.setVisibility(View.VISIBLE);
|
||||
|
||||
getStatuses();
|
||||
getPullRequest();
|
||||
|
||||
viewBinding.prInfoLayout.setVisibility(View.VISIBLE);
|
||||
String displayName;
|
||||
if (!issue.getPullRequest().getUser().getFullName().isEmpty()) {
|
||||
displayName = issue.getPullRequest().getUser().getFullName();
|
||||
User user = issue.getIssue().getUser();
|
||||
if (user != null && user.getFullName() != null && !user.getFullName().isEmpty()) {
|
||||
displayName = user.getFullName();
|
||||
} else {
|
||||
displayName = issue.getPullRequest().getUser().getLogin();
|
||||
displayName = user != null && user.getLogin() != null ? user.getLogin() : "Unknown";
|
||||
}
|
||||
|
||||
PullRequest pr = issue.getPullRequest();
|
||||
if (pr != null && pr.getHead() != null && pr.getBase() != null) {
|
||||
viewBinding.prInfo.setText(
|
||||
getString(
|
||||
R.string.pr_info,
|
||||
displayName,
|
||||
pr.getHead().getRef(),
|
||||
pr.getBase().getRef()));
|
||||
}
|
||||
viewBinding.prInfo.setText(
|
||||
getString(
|
||||
R.string.pr_info,
|
||||
displayName,
|
||||
issue.getPullRequest().getHead().getRef(),
|
||||
issue.getPullRequest().getBase().getRef()));
|
||||
|
||||
if (issue.getIssue().getPullRequest().isMerged()) { // merged
|
||||
|
||||
@@ -1530,19 +1542,33 @@ public class IssueDetailActivity extends BaseActivity
|
||||
public void onResponse(
|
||||
@NonNull Call<PullRequest> call,
|
||||
@NonNull Response<PullRequest> response) {
|
||||
pullRequestFetchAttempted = true;
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
issue.setPullRequest(response.body());
|
||||
loadingFinishedPr = true;
|
||||
updateMenuState();
|
||||
} else {
|
||||
loadingFinishedPr = true;
|
||||
}
|
||||
checkAndInitWithIssue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(
|
||||
@NonNull Call<PullRequest> call, @NonNull Throwable t) {}
|
||||
@NonNull Call<PullRequest> call, @NonNull Throwable t) {
|
||||
pullRequestFetchAttempted = true;
|
||||
loadingFinishedPr = true;
|
||||
checkAndInitWithIssue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void checkAndInitWithIssue() {
|
||||
if (loadingFinishedIssue || pullRequestFetchAttempted) {
|
||||
initWithIssue();
|
||||
}
|
||||
}
|
||||
|
||||
private void getRepoInfo() {
|
||||
Call<Repository> call =
|
||||
RetrofitClient.getApiInterface(ctx)
|
||||
@@ -1800,15 +1826,16 @@ public class IssueDetailActivity extends BaseActivity
|
||||
|
||||
private void getStatuses() {
|
||||
|
||||
PullRequest pr = issue.getPullRequest();
|
||||
if (pr == null || pr.getHead() == null || pr.getHead().getRef() == null) {
|
||||
viewBinding.statusesLvMain.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
String headRef = pr.getHead().getSha();
|
||||
|
||||
RetrofitClient.getApiInterface(ctx)
|
||||
.repoListStatuses(
|
||||
repoOwner,
|
||||
repoName,
|
||||
issue.getRepository().getBranchRef(),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null)
|
||||
.repoListStatuses(repoOwner, repoName, headRef, null, null, null, null)
|
||||
.enqueue(
|
||||
new Callback<>() {
|
||||
|
||||
@@ -1862,6 +1889,7 @@ public class IssueDetailActivity extends BaseActivity
|
||||
public void onFailure(
|
||||
@NonNull Call<List<CommitStatus>> call, @NonNull Throwable t) {
|
||||
|
||||
viewBinding.statusesLvMain.setVisibility(View.GONE);
|
||||
checkLoading();
|
||||
if (ctx != null) {
|
||||
Toasty.error(ctx, getString(R.string.genericError));
|
||||
|
||||
@@ -61,7 +61,6 @@ import org.mian.gitnex.helpers.AppUtil;
|
||||
import org.mian.gitnex.helpers.ChangeLog;
|
||||
import org.mian.gitnex.helpers.Toasty;
|
||||
import org.mian.gitnex.structs.BottomSheetListener;
|
||||
import org.mian.gitnex.structs.FragmentRefreshListener;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
||||
@@ -120,6 +119,8 @@ public class MainActivity extends BaseActivity
|
||||
|
||||
noConnection = false;
|
||||
|
||||
loadUserInfo();
|
||||
|
||||
Toolbar toolbar = activityMainBinding.toolbar;
|
||||
toolbarTitle = activityMainBinding.toolbarTitle;
|
||||
|
||||
@@ -501,24 +502,6 @@ public class MainActivity extends BaseActivity
|
||||
}
|
||||
}
|
||||
|
||||
handler.postDelayed(
|
||||
() -> {
|
||||
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
|
||||
if (!connToInternet) {
|
||||
|
||||
if (!noConnection) {
|
||||
Toasty.error(
|
||||
ctx, getResources().getString(R.string.checkNetConnection));
|
||||
}
|
||||
noConnection = true;
|
||||
} else {
|
||||
|
||||
loadUserInfo();
|
||||
noConnection = false;
|
||||
}
|
||||
},
|
||||
750);
|
||||
|
||||
handler.postDelayed(
|
||||
() -> {
|
||||
boolean connToInternet = AppUtil.hasNetworkConnection(appCtx);
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.bumptech.glide.load.model.GlideUrl;
|
||||
import com.bumptech.glide.module.AppGlideModule;
|
||||
import java.io.InputStream;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.mian.gitnex.activities.BaseActivity;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
@@ -26,7 +27,11 @@ public class GlideService extends AppGlideModule {
|
||||
@Override
|
||||
public void registerComponents(
|
||||
@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
|
||||
OkHttpClient okHttpClient = GlideHttpClient.getUnsafeOkHttpClient();
|
||||
String token = "";
|
||||
if (context instanceof BaseActivity) {
|
||||
token = ((BaseActivity) context).getAccount().getAuthorization();
|
||||
}
|
||||
OkHttpClient okHttpClient = RetrofitClient.getOkHttpClient(context, token);
|
||||
registry.replace(
|
||||
GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.mian.gitnex.clients;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import java.io.File;
|
||||
@@ -15,12 +14,16 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.Cache;
|
||||
import okhttp3.CacheControl;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.gitnex.tea4j.v2.apis.AdminApi;
|
||||
import org.gitnex.tea4j.v2.apis.IssueApi;
|
||||
import org.gitnex.tea4j.v2.apis.MiscellaneousApi;
|
||||
@@ -52,89 +55,120 @@ public class RetrofitClient {
|
||||
|
||||
private static final Map<String, ApiInterface> apiInterfaces = new ConcurrentHashMap<>();
|
||||
private static final Map<String, WebApi> webInterfaces = new ConcurrentHashMap<>();
|
||||
private static final int CACHE_SIZE_MB = 50;
|
||||
private static final int MAX_AGE_SECONDS = 60 * 5;
|
||||
private static final int MAX_STALE_SECONDS = 60 * 60 * 24 * 30;
|
||||
|
||||
private static Retrofit createRetrofit(
|
||||
Context context,
|
||||
String instanceUrl,
|
||||
boolean cacheEnabled,
|
||||
String token,
|
||||
File cacheFile) {
|
||||
private static OkHttpClient buildOkHttpClient(Context context, String token, File cacheFile) {
|
||||
|
||||
// HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
|
||||
// logging.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
|
||||
try {
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
|
||||
MemorizingTrustManager memorizingTrustManager = new MemorizingTrustManager(context);
|
||||
sslContext.init(
|
||||
null, new X509TrustManager[] {memorizingTrustManager}, new SecureRandom());
|
||||
|
||||
ApiKeyAuth auth = new ApiKeyAuth("header", "Authorization");
|
||||
auth.setApiKey(token);
|
||||
|
||||
OkHttpClient.Builder okHttpClient =
|
||||
new OkHttpClient.Builder()
|
||||
// .addInterceptor(logging)
|
||||
.addInterceptor(auth)
|
||||
.sslSocketFactory(sslContext.getSocketFactory(), memorizingTrustManager)
|
||||
.hostnameVerifier(
|
||||
memorizingTrustManager.wrapHostnameVerifier(
|
||||
HttpsURLConnection.getDefaultHostnameVerifier()));
|
||||
|
||||
if (cacheEnabled && cacheFile != null) {
|
||||
if (cacheFile != null) {
|
||||
int cacheSize = CACHE_SIZE_MB;
|
||||
try {
|
||||
cacheSize =
|
||||
FilesData.returnOnlyNumberFileSize(
|
||||
AppDatabaseSettings.getSettingsValue(
|
||||
context, AppDatabaseSettings.APP_DATA_CACHE_SIZE_KEY));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
cacheSize = cacheSize * 1024 * 1024;
|
||||
|
||||
int cacheSize =
|
||||
FilesData.returnOnlyNumberFileSize(
|
||||
AppDatabaseSettings.getSettingsValue(
|
||||
context,
|
||||
AppDatabaseSettings.APP_DATA_CACHE_SIZE_KEY))
|
||||
* 1024
|
||||
* 1024;
|
||||
Cache cache = new Cache(cacheFile, cacheSize);
|
||||
File cacheDir = new File(context.getCacheDir(), "http-cache");
|
||||
if (!cacheDir.exists()) {
|
||||
if (!cacheDir.mkdirs()) {
|
||||
throw new RuntimeException(
|
||||
"Failed to create cache directory: " + cacheDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
Cache cache = new Cache(cacheDir, cacheSize);
|
||||
okHttpClient.cache(cache);
|
||||
|
||||
Interceptor cacheInterceptor =
|
||||
chain -> {
|
||||
Request originalRequest = chain.request();
|
||||
boolean hasNetwork = AppUtil.hasNetworkConnection(context);
|
||||
CacheControl.Builder cacheControlBuilder = new CacheControl.Builder();
|
||||
if (hasNetwork) {
|
||||
cacheControlBuilder.maxAge(MAX_AGE_SECONDS, TimeUnit.SECONDS);
|
||||
} else {
|
||||
cacheControlBuilder
|
||||
.onlyIfCached()
|
||||
.maxStale(MAX_STALE_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
CacheControl cacheControl = cacheControlBuilder.build();
|
||||
|
||||
Request modifiedRequest =
|
||||
originalRequest.newBuilder().cacheControl(cacheControl).build();
|
||||
|
||||
return chain.proceed(modifiedRequest);
|
||||
};
|
||||
|
||||
Interceptor forceCacheInterceptor =
|
||||
chain -> {
|
||||
Request request = chain.request();
|
||||
Response response = chain.proceed(request);
|
||||
if (request.method().equals("GET") && response.isSuccessful()) {
|
||||
return response.newBuilder()
|
||||
.header(
|
||||
"Cache-Control",
|
||||
"public, max-age=" + MAX_AGE_SECONDS)
|
||||
.removeHeader("Pragma")
|
||||
.build();
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
okHttpClient
|
||||
.cache(cache)
|
||||
.addInterceptor(
|
||||
chain -> {
|
||||
Request request = chain.request();
|
||||
|
||||
request =
|
||||
AppUtil.hasNetworkConnection(context)
|
||||
? request.newBuilder()
|
||||
.header(
|
||||
"Cache-Control",
|
||||
"public, max-age=" + 60)
|
||||
.build()
|
||||
: request.newBuilder()
|
||||
.header(
|
||||
"Cache-Control",
|
||||
"public, only-if-cached, max-stale="
|
||||
+ 60 * 60 * 24 * 30)
|
||||
.build();
|
||||
|
||||
return chain.proceed(request);
|
||||
});
|
||||
.addInterceptor(auth)
|
||||
.addInterceptor(cacheInterceptor)
|
||||
.addNetworkInterceptor(forceCacheInterceptor);
|
||||
}
|
||||
|
||||
return new Retrofit.Builder()
|
||||
.baseUrl(instanceUrl)
|
||||
.client(okHttpClient.build())
|
||||
.addConverterFactory(ScalarsConverterFactory.create())
|
||||
.addConverterFactory(
|
||||
GsonConverterFactory.create(
|
||||
new GsonBuilder()
|
||||
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||
.create()))
|
||||
.addConverterFactory(DateQueryConverterFactory.create())
|
||||
.build();
|
||||
return okHttpClient.build();
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
Log.e("onFailureRetrofit", e.toString());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
private static Retrofit createRetrofit(
|
||||
Context context, String instanceUrl, String token, File cacheFile) {
|
||||
OkHttpClient okHttpClient = buildOkHttpClient(context, token, cacheFile);
|
||||
return new Retrofit.Builder()
|
||||
.baseUrl(instanceUrl)
|
||||
.client(okHttpClient)
|
||||
.addConverterFactory(ScalarsConverterFactory.create())
|
||||
.addConverterFactory(
|
||||
GsonConverterFactory.create(
|
||||
new GsonBuilder()
|
||||
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||
.create()))
|
||||
.addConverterFactory(DateQueryConverterFactory.create())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static OkHttpClient getOkHttpClient(Context context, String token) {
|
||||
File cacheFile = new File(context.getCacheDir(), "http-cache");
|
||||
return buildOkHttpClient(context, token, cacheFile);
|
||||
}
|
||||
|
||||
public static ApiInterface getApiInterface(Context context) {
|
||||
@@ -146,10 +180,8 @@ public class RetrofitClient {
|
||||
}
|
||||
|
||||
public static WebApi getWebInterface(Context context) {
|
||||
|
||||
String instanceUrl = ((BaseActivity) context).getAccount().getAccount().getInstanceUrl();
|
||||
instanceUrl = instanceUrl.substring(0, instanceUrl.lastIndexOf("api/v1/"));
|
||||
|
||||
return getWebInterface(
|
||||
context,
|
||||
instanceUrl,
|
||||
@@ -158,7 +190,6 @@ public class RetrofitClient {
|
||||
}
|
||||
|
||||
public static WebApi getWebInterface(Context context, String url) {
|
||||
|
||||
return getWebInterface(
|
||||
context,
|
||||
url,
|
||||
@@ -168,45 +199,35 @@ public class RetrofitClient {
|
||||
|
||||
public static ApiInterface getApiInterface(
|
||||
Context context, String url, String token, File cacheFile) {
|
||||
|
||||
String key = token.hashCode() + "@" + url;
|
||||
if (!apiInterfaces.containsKey(key)) {
|
||||
synchronized (RetrofitClient.class) {
|
||||
if (!apiInterfaces.containsKey(key)) {
|
||||
|
||||
ApiInterface apiInterface =
|
||||
Objects.requireNonNull(
|
||||
createRetrofit(context, url, true, token, cacheFile))
|
||||
Objects.requireNonNull(createRetrofit(context, url, token, cacheFile))
|
||||
.create(ApiInterface.class);
|
||||
apiInterfaces.put(key, apiInterface);
|
||||
|
||||
return apiInterface;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return apiInterfaces.get(key);
|
||||
}
|
||||
|
||||
public static WebApi getWebInterface(
|
||||
Context context, String url, String token, File cacheFile) {
|
||||
|
||||
String key = token.hashCode() + "@" + url;
|
||||
if (!webInterfaces.containsKey(key)) {
|
||||
synchronized (RetrofitClient.class) {
|
||||
if (!webInterfaces.containsKey(key)) {
|
||||
|
||||
WebApi webInterface =
|
||||
Objects.requireNonNull(
|
||||
createRetrofit(context, url, false, token, cacheFile))
|
||||
Objects.requireNonNull(createRetrofit(context, url, token, cacheFile))
|
||||
.create(WebApi.class);
|
||||
webInterfaces.put(key, webInterface);
|
||||
|
||||
return webInterface;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return webInterfaces.get(key);
|
||||
}
|
||||
|
||||
@@ -224,7 +245,6 @@ public class RetrofitClient {
|
||||
PackageApi {}
|
||||
|
||||
private static class DateQueryConverterFactory extends Converter.Factory {
|
||||
|
||||
public static DateQueryConverterFactory create() {
|
||||
return new DateQueryConverterFactory();
|
||||
}
|
||||
@@ -240,16 +260,13 @@ public class RetrofitClient {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class DateQueryConverter implements Converter<Date, String> {
|
||||
|
||||
private static class DateQueryConverter implements Converter<Date, String> {
|
||||
static final DateQueryConverter INSTANCE = new DateQueryConverter();
|
||||
|
||||
private static final ThreadLocal<DateFormat> DF =
|
||||
new ThreadLocal<>() {
|
||||
|
||||
@Override
|
||||
public DateFormat initialValue() {
|
||||
|
||||
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.mian.gitnex.fragments;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
@@ -24,12 +23,8 @@ import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import moe.feng.common.view.breadcrumbs.DefaultBreadcrumbsCallback;
|
||||
import moe.feng.common.view.breadcrumbs.model.BreadcrumbItem;
|
||||
import org.gitnex.tea4j.v2.models.Branch;
|
||||
import org.gitnex.tea4j.v2.models.ContentsResponse;
|
||||
import org.mian.gitnex.R;
|
||||
@@ -95,31 +90,6 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
|
||||
|
||||
binding.branchTitle.setText(repository.getBranchRef());
|
||||
|
||||
binding.breadcrumbsView.setItems(
|
||||
new ArrayList<>(
|
||||
Collections.singletonList(
|
||||
BreadcrumbItem.createSimpleItem(repository.getBranchRef()))));
|
||||
// noinspection unchecked
|
||||
binding.breadcrumbsView.setCallback(
|
||||
new DefaultBreadcrumbsCallback<BreadcrumbItem>() {
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void onNavigateBack(BreadcrumbItem item, int position) {
|
||||
|
||||
if (position == 0) {
|
||||
path.clear();
|
||||
} else {
|
||||
path.pop(path.size() - position);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNavigateNewLocation(
|
||||
BreadcrumbItem newItem, int changedPosition) {}
|
||||
});
|
||||
|
||||
requireActivity()
|
||||
.getOnBackPressedDispatcher()
|
||||
.addCallback(
|
||||
@@ -136,7 +106,6 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
|
||||
return;
|
||||
}
|
||||
path.remove(path.size() - 1);
|
||||
binding.breadcrumbsView.removeLastItem();
|
||||
if (path.size() == 0) {
|
||||
fetchDataAsync(
|
||||
repository.getOwner(),
|
||||
@@ -163,19 +132,12 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
|
||||
repoBranch -> {
|
||||
repository.setBranchRef(repoBranch);
|
||||
path.clear();
|
||||
binding.breadcrumbsView.setItems(
|
||||
new ArrayList<>(
|
||||
Collections.singletonList(
|
||||
BreadcrumbItem.createSimpleItem(
|
||||
repository.getBranchRef()))));
|
||||
refresh();
|
||||
});
|
||||
|
||||
String dir = requireActivity().getIntent().getStringExtra("dir");
|
||||
if (dir != null) {
|
||||
for (String segment : dir.split("/")) {
|
||||
binding.breadcrumbsView.addItem(
|
||||
new BreadcrumbItem(Collections.singletonList(segment)));
|
||||
path.add(segment);
|
||||
}
|
||||
}
|
||||
@@ -254,8 +216,6 @@ public class FilesFragment extends Fragment implements FilesAdapter.FilesAdapter
|
||||
switch (file.getType()) {
|
||||
case "dir":
|
||||
path.addWithoutEncoding(file.getName());
|
||||
binding.breadcrumbsView.addItem(
|
||||
new BreadcrumbItem(Collections.singletonList(file.getName())));
|
||||
refresh();
|
||||
break;
|
||||
|
||||
|
||||
@@ -492,13 +492,6 @@ public class RepoInfoFragment extends Fragment {
|
||||
requireActivity()
|
||||
.runOnUiThread(
|
||||
() -> {
|
||||
Toasty.error(
|
||||
ctx,
|
||||
ctx
|
||||
.getString(
|
||||
R
|
||||
.string
|
||||
.genericError));
|
||||
binding
|
||||
.fileContentsFrameHeader
|
||||
.setVisibility(
|
||||
|
||||
@@ -15,37 +15,6 @@
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="?attr/materialCardViewElevatedStyle"
|
||||
android:layout_marginStart="@dimen/dimen8dp"
|
||||
android:layout_marginEnd="@dimen/dimen8dp"
|
||||
android:layout_marginTop="@dimen/dimen8dp"
|
||||
android:visibility="gone"
|
||||
app:cardElevation="@dimen/dimen0dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:background="?attr/materialCardBackgroundColor"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<moe.feng.common.view.breadcrumbs.BreadcrumbsView
|
||||
android:id="@+id/breadcrumbs_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:saveEnabled="false"
|
||||
android:text="@string/filesBreadcrumbRoot"
|
||||
app:CustomTextSize="@dimen/dimen16sp"
|
||||
app:SelectedTextColor="?attr/primaryTextColor"
|
||||
app:UnSelectedTextColor="?attr/inputSelectedColor" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<!-- branch section -->
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/branch_section"
|
||||
|
||||
@@ -1,27 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<changelog>
|
||||
|
||||
<release version="8.0.0" versioncode="800">
|
||||
<change>New: Create a branch when creating, editing, or deleting a file</change>
|
||||
<change>New: Search within files</change>
|
||||
<change>New: Show tags if there are no releases</change>
|
||||
<change>New: Display a user activity heatmap on the profile</change>
|
||||
<change>New: Add pinch-and-zoom support for files</change>
|
||||
<change>New: Mention users in issues, pull requests, and comments</change>
|
||||
<change>New: Filter issues by labels</change>
|
||||
<change>New: Filter issues where I am mentioned</change>
|
||||
<change>New: Manage dependencies for issues and pull requests (view, add, remove)</change>
|
||||
<change>New: Manage tracked time (view, add, remove)</change>
|
||||
<change>New: Add a Created by Me filter to My Issues</change>
|
||||
<change>Improvement: UI enhancements</change>
|
||||
<change>Improvement: Paginate repository stargazers and watchers</change>
|
||||
<change>Improvement: Paginate organization members and repository collaborators</change>
|
||||
<change>Improvement: Add pagination for repository branches</change>
|
||||
<change>Improvement: Improve the loading of large files in the file viewer</change>
|
||||
<change>Improvement: Update translations</change>
|
||||
<change>Bugfix: Fix the commits UI</change>
|
||||
<change>Bugfix: Fix the issues progress bar</change>
|
||||
<change>Removal: HTTP Basic Authentication (username/password login) has been removed</change>
|
||||
<release version="9.0.0-dev" versioncode="895">
|
||||
<change>Under development</change>
|
||||
</release>
|
||||
|
||||
</changelog>
|
||||
|
||||
Reference in New Issue
Block a user