Handle popular links (#730)

Fix settings layout

Merge branch 'master' into deeplinks

Support for all links, check gitea instance, add progress indicator

Enhance account checks, improve the experience of coming from links

Merge branch 'master' into deeplinks

Update libs

Minor layout fixes

gradle update

Fix show/hide views

Handle pr, repos. Handle settings for no action.

open issue from link

Add new settings section translation ready - General for generic settings

wip on handle popular links

Co-authored-by: M M Arif <mmarif@swatian.com>
Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: 6543 <6543@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/730
This commit is contained in:
M M Arif 2020-10-23 20:13:13 +02:00
parent 044f6191bf
commit 8e86fa668d
33 changed files with 1099 additions and 155 deletions

View File

@ -19,18 +19,9 @@
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" alias="false" withSubpackages="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
<package name="java.util" withSubpackages="false" static="false" />
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
<package name="io.ktor" withSubpackages="true" static="false" />
</value>
</option>
</JetCodeStyleSettings>
@ -180,4 +171,4 @@
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>
</component>

View File

@ -11,7 +11,7 @@ GitNex is licensed under GPLv3 License. See the LICENSE file for the full licens
## Downloads
[<img alt='Get it on F-droid' src='https://gitlab.com/fdroid/artwork/raw/master/badge/get-it-on.png' height="80"/>](https://f-droid.org/en/packages/org.mian.gitnex/)
[<img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png' height="80"/>](https://play.google.com/store/apps/details?id=org.mian.gitnex.pro)
[<img alt='Download builds and releases' src='assets/apk-badge.png' height="82"/>](https://cloud.swatian.com/s/DN7E5xxtaw4fRbE)
[<img alt='Download builds and releases' src='https://codeberg.org/gitnex/GitNex/src/branch/master/assets/apk-badge.png' height="82"/>](https://cloud.swatian.com/s/DN7E5xxtaw4fRbE)
## Note about Gitea version
Please make sure that you are on latest stable release or later for better app experience.

View File

@ -153,12 +153,31 @@
<activity
android:name=".activities.CreatePullRequestActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<activity
android:name=".activities.SettingsGeneralActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" />
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data android:name="com.samsung.android.keepalive.density" android:value="true"/>
<!-- Version >= 3.0. DeX Dual Mode support -->
<meta-data android:name="com.samsung.android.multidisplay.keep_process_alive" android:value="true"/>
<!-- deep links -->
<activity
android:name=".activities.DeepLinksActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="*" />
</intent-filter>
</activity>
<!-- deep links -->
</application>
</manifest>

View File

@ -0,0 +1,486 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.mian.gitnex.R;
import org.mian.gitnex.clients.RetrofitClient;
import org.mian.gitnex.database.api.RepositoriesApi;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.Repository;
import org.mian.gitnex.database.models.UserAccount;
import org.mian.gitnex.databinding.ActivityDeeplinksBinding;
import org.mian.gitnex.helpers.PathsHelper;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import org.mian.gitnex.helpers.UrlHelper;
import org.mian.gitnex.models.GiteaVersion;
import org.mian.gitnex.models.PullRequests;
import org.mian.gitnex.models.UserRepositories;
import java.net.URI;
import java.util.List;
import java.util.Objects;
import io.mikael.urlbuilder.UrlBuilder;
import retrofit2.Call;
import retrofit2.Callback;
/**
* Author M M Arif
*/
public class DeepLinksActivity extends BaseActivity {
private ActivityDeeplinksBinding viewBinding;
private Context ctx = this;
private Context appCtx;
private TinyDB tinyDb;
private String currentInstance;
private String instanceToken;
private Intent mainIntent;
private Intent issueIntent;
private Intent repoIntent;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_deeplinks;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
tinyDb = new TinyDB(appCtx);
viewBinding = ActivityDeeplinksBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
mainIntent = new Intent(ctx, MainActivity.class);
issueIntent = new Intent(ctx, IssueDetailActivity.class);
repoIntent = new Intent(ctx, RepoDetailActivity.class);
Intent intent = getIntent();
Uri data = intent.getData();
assert data != null;
// check for login
if(!tinyDb.getBoolean("loggedInMode")) {
finish();
ctx.startActivity(new Intent(ctx, LoginActivity.class));
}
// check for the links(URI) to be in the db
UserAccountsApi userAccountsApi = new UserAccountsApi(ctx);
List<UserAccount> userAccounts = userAccountsApi.usersAccounts();
if(userAccounts.size() > 0) {
String hostUri;
for(int i = 0; i < userAccounts.size(); i++) {
hostUri = userAccounts.get(i).getInstanceUrl();
currentInstance = userAccounts.get(i).getInstanceUrl();
instanceToken = userAccounts.get(i).getToken();
if(!hostUri.contains(Objects.requireNonNull(data.getHost()))) {
// check for valid instance
checkInstance(data);
return;
}
}
}
// redirect to proper fragment/activity, If no action is there, show options where user to want to go like repos, profile, notifications etc
if(data.getPathSegments().size() > 0) {
viewBinding.progressBar.setVisibility(View.GONE);
String[] restOfUrl = Objects.requireNonNull(data.getPath()).split("/");
if(data.getPathSegments().contains("issues")) { // issue
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("issues") & StringUtils.isNumeric(data.getLastPathSegment())) {
issueIntent.putExtra("issueNumber", data.getLastPathSegment());
tinyDb.putString("issueNumber", data.getLastPathSegment());
tinyDb.putString("issueType", "Issue");
tinyDb.putString("repoFullName", restOfUrl[restOfUrl.length - 4] + "/" + restOfUrl[restOfUrl.length - 3]);
final String repoOwner = restOfUrl[restOfUrl.length - 4];
final String repoName = restOfUrl[restOfUrl.length - 3];
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository dataRepo = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", dataRepo.getRepositoryId());
}
ctx.startActivity(issueIntent);
finish();
}
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("issues")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 3], restOfUrl[restOfUrl.length - 2], "issue");
}, 500);
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
else if(data.getPathSegments().contains("pulls")) { // pr
if(!Objects.requireNonNull(data.getLastPathSegment()).contains("pulls") & StringUtils.isNumeric(data.getLastPathSegment())) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
getPullRequest(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 4], restOfUrl[restOfUrl.length - 3],
Integer.parseInt(data.getLastPathSegment()));
}, 500);
}
else if(Objects.requireNonNull(data.getLastPathSegment()).contains("pulls")) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 3], restOfUrl[restOfUrl.length - 2], "pull");
}, 500);
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
else if(!restOfUrl[restOfUrl.length - 2].equals("") & !restOfUrl[restOfUrl.length - 1].equals("")) { // go to repo
new Handler(Looper.getMainLooper()).postDelayed(() -> {
goToRepoSection(currentInstance, instanceToken, restOfUrl[restOfUrl.length - 2], restOfUrl[restOfUrl.length - 1], "repo");
}, 500);
}
else { // no action, show options
if(tinyDb.getInt("defaultScreenId") == 1) { // repos
mainIntent.putExtra("launchFragmentByLinkHandler", "repos");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDb.getInt("defaultScreenId") == 2) { // org
mainIntent.putExtra("launchFragmentByLinkHandler", "org");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDb.getInt("defaultScreenId") == 3) { // notifications
mainIntent.putExtra("launchFragmentByLinkHandler", "notification");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDb.getInt("defaultScreenId") == 4) { // explore
mainIntent.putExtra("launchFragmentByLinkHandler", "explore");
ctx.startActivity(mainIntent);
finish();
}
else if(tinyDb.getInt("defaultScreenId") == 0) { // show options
viewBinding.noActionFrame.setVisibility(View.VISIBLE);
viewBinding.addNewAccountFrame.setVisibility(View.GONE);
viewBinding.repository.setOnClickListener(repository -> {
tinyDb.putInt("defaultScreenId", 1);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.navRepos));
mainIntent.putExtra("launchFragmentByLinkHandler", "repos");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.organization.setOnClickListener(organization -> {
tinyDb.putInt("defaultScreenId", 2);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.navOrgs));
mainIntent.putExtra("launchFragmentByLinkHandler", "org");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.notification.setOnClickListener(notification -> {
tinyDb.putInt("defaultScreenId", 3);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.pageTitleNotifications));
mainIntent.putExtra("launchFragmentByLinkHandler", "notification");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.explore.setOnClickListener(explore -> {
tinyDb.putInt("defaultScreenId", 4);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.navExplore));
mainIntent.putExtra("launchFragmentByLinkHandler", "explore");
ctx.startActivity(mainIntent);
finish();
});
viewBinding.launchApp2.setOnClickListener(launchApp2 -> {
tinyDb.putInt("defaultScreenId", 0);
tinyDb.putString("defaultScreenStr", getResources().getString(R.string.generalDeepLinkSelectedText));
ctx.startActivity(mainIntent);
finish();
});
}
}
}
else {
ctx.startActivity(mainIntent);
finish();
}
}
private void checkInstance(Uri data) {
URI host;
if(data.getPort() > 0) {
host = UrlBuilder.fromString(UrlHelper.fixScheme(data.getHost(), "https")).withPort(data.getPort()).toUri();
}
else {
host = UrlBuilder.fromString(UrlHelper.fixScheme(data.getHost(), "https")).toUri();
}
URI instanceUrl = UrlBuilder.fromUri(host).withScheme(data.getScheme().toLowerCase()).withPath(PathsHelper.join(host.getPath(), "/api/v1/"))
.toUri();
Call<GiteaVersion> callVersion;
callVersion = RetrofitClient.getInstance(String.valueOf(instanceUrl), ctx).getApiInterface().getGiteaVersion();
callVersion.enqueue(new Callback<GiteaVersion>() {
@Override
public void onResponse(@NonNull final Call<GiteaVersion> callVersion, @NonNull retrofit2.Response<GiteaVersion> responseVersion) {
if(responseVersion.isSuccessful() || responseVersion.code() == 403) {
viewBinding.progressBar.setVisibility(View.GONE);
viewBinding.addNewAccountFrame.setVisibility(View.VISIBLE);
viewBinding.noActionFrame.setVisibility(View.GONE);
viewBinding.addAccountText.setText(String.format(getResources().getString(R.string.accountDoesNotExist), data.getHost()));
viewBinding.addNewAccount.setOnClickListener(addNewAccount -> {
Intent accountIntent = new Intent(ctx, AddNewAccountActivity.class);
startActivity(accountIntent);
finish();
});
viewBinding.openInBrowser.setOnClickListener(addNewAccount -> {
Intent intentBrowser = new Intent();
intentBrowser.setAction(Intent.ACTION_VIEW);
intentBrowser.addCategory(Intent.CATEGORY_BROWSABLE);
intentBrowser.setData(Uri.parse(String.valueOf(host)));
startActivity(intentBrowser);
finish();
});
viewBinding.launchApp.setOnClickListener(launchApp -> {
startActivity(mainIntent);
finish();
});
}
}
@Override
public void onFailure(@NonNull Call<GiteaVersion> callVersion, @NonNull Throwable t) {
Toasty.error(ctx, getResources().getString(R.string.versionUnknown));
finish();
}
});
}
private void getPullRequest(String url, String token, String repoOwner, String repoName, int index) {
Call<PullRequests> call = RetrofitClient
.getInstance(url, ctx)
.getApiInterface()
.getPullRequestByIndex(token, repoOwner, repoName, index);
call.enqueue(new Callback<PullRequests>() {
@Override
public void onResponse(@NonNull Call<PullRequests> call, @NonNull retrofit2.Response<PullRequests> response) {
PullRequests prInfo = response.body();
if (response.code() == 200) {
assert prInfo != null;
issueIntent.putExtra("issueNumber", index);
issueIntent.putExtra("prMergeable", prInfo.isMergeable());
if(prInfo.getHead() != null) {
issueIntent.putExtra("prHeadBranch", prInfo.getHead().getRef());
tinyDb.putString("prHeadBranch", prInfo.getHead().getRef());
if(prInfo.getHead().getRepo() != null) {
tinyDb.putString("prIsFork", String.valueOf(prInfo.getHead().getRepo().isFork()));
tinyDb.putString("prForkFullName", prInfo.getHead().getRepo().getFull_name());
}
else {
// pull was done from a deleted fork
tinyDb.putString("prIsFork", "true");
tinyDb.putString("prForkFullName", ctx.getString(R.string.prDeletedFrok));
}
}
tinyDb.putString("issueNumber", String.valueOf(index));
tinyDb.putString("prMergeable", String.valueOf(prInfo.isMergeable()));
tinyDb.putString("issueType", "Pull");
tinyDb.putString("repoFullName", repoOwner + "/" + repoName);
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository dataRepo = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", dataRepo.getRepositoryId());
}
ctx.startActivity(issueIntent);
finish();
}
else {
Log.e("onFailure-links-pr", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<PullRequests> call, @NonNull Throwable t) {
Log.e("onFailure-links-pr", t.toString());
}
});
}
private void goToRepoSection(String url, String token, String repoOwner, String repoName, String type) {
Call<UserRepositories> call = RetrofitClient
.getInstance(url, ctx)
.getApiInterface()
.getUserRepository(token, repoOwner, repoName);
call.enqueue(new Callback<UserRepositories>() {
@Override
public void onResponse(@NonNull Call<UserRepositories> call, @NonNull retrofit2.Response<UserRepositories> response) {
UserRepositories repoInfo = response.body();
if (response.code() == 200) {
assert repoInfo != null;
repoIntent.putExtra("repoFullName", repoInfo.getFullName());
repoIntent.putExtra("goToSection", "yes");
repoIntent.putExtra("goToSectionType", type);
tinyDb.putString("repoFullName", repoInfo.getFullName());
if(repoInfo.getPrivateFlag()) {
tinyDb.putString("repoType", getResources().getString(R.string.strPrivate));
}
else {
tinyDb.putString("repoType", getResources().getString(R.string.strPublic));
}
tinyDb.putBoolean("isRepoAdmin", repoInfo.getPermissions().isAdmin());
tinyDb.putString("repoBranch", repoInfo.getDefault_branch());
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
RepositoriesApi repositoryData = new RepositoriesApi(ctx);
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
if(count == 0) {
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", id);
}
else {
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
tinyDb.putLong("repositoryId", data.getRepositoryId());
}
ctx.startActivity(repoIntent);
finish();
}
else {
Log.e("onFailure-links", String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call<UserRepositories> call, @NonNull Throwable t) {
Log.e("onFailure-links", t.toString());
}
});
}
}

View File

@ -2,6 +2,7 @@ package org.mian.gitnex.activities;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
@ -790,7 +791,6 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
viewBinding.progressBar.setVisibility(View.GONE);
}
else if(response.code() == 401) {
AlertDialogs.authorizationTokenRevokedDialog(ctx, getResources().getString(R.string.alertDialogTokenRevokedTitle),
@ -799,6 +799,22 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
getResources().getString(R.string.alertDialogTokenRevokedCopyPositiveButton));
}
else if(response.code() == 404) {
if(tinyDb.getString("issueType").equals("Issue")) {
Toasty.warning(ctx, getResources().getString(R.string.noDataIssueTab));
}
else if(tinyDb.getString("issueType").equals("Pull")) {
Toasty.warning(ctx, getResources().getString(R.string.noDataPullRequests));
}
Intent mainIntent = new Intent(ctx, MainActivity.class);
ctx.startActivity(mainIntent);
finish();
}
}

View File

@ -79,6 +79,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
private TextView toolbarTitle;
final Context ctx = this;
private Context appCtx;
private static TinyDB tinyDb;
private Typeface myTypeface;
private String instanceUrl;
@ -101,7 +102,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
final TinyDB tinyDb = new TinyDB(appCtx);
tinyDb = new TinyDB(appCtx);
tinyDb.putBoolean("noConnection", false);
Intent mainIntent = getIntent();
@ -347,6 +348,36 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
}
}
String launchFragmentByHandler = mainIntent.getStringExtra("launchFragmentByLinkHandler");
if(launchFragmentByHandler != null) {
mainIntent.removeExtra("launchFragmentByLinkHandler");
switch(launchFragmentByHandler) {
case "repos":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new RepositoriesFragment()).commit();
navigationView.setCheckedItem(R.id.nav_repositories);
return;
case "org":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OrganizationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_organizations);
return;
case "notification":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new NotificationsFragment()).commit();
navigationView.setCheckedItem(R.id.nav_notifications);
return;
case "explore":
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
navigationView.setCheckedItem(R.id.nav_explore);
return;
}
}
if(savedInstanceState == null) {
if(!new Version(tinyDb.getString("giteaVersion")).higherOrEqual("1.12.3")) {
@ -577,7 +608,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public static void logout(Activity activity, Context ctx) {
TinyDB tinyDb = new TinyDB(ctx.getApplicationContext());
tinyDb.putBoolean("loggedInMode", false);
tinyDb.remove("basicAuthPassword");
tinyDb.putBoolean("basicAuthFlag", false);

View File

@ -238,6 +238,25 @@ public class RepoDetailActivity extends BaseActivity implements BottomSheetRepoF
}
}
Intent mainIntent = getIntent();
String goToSection = mainIntent.getStringExtra("goToSection");
String goToSectionType = mainIntent.getStringExtra("goToSectionType");
if(goToSection != null) {
mainIntent.removeExtra("goToSection");
mainIntent.removeExtra("goToSectionType");
if(goToSectionType.equals("issue")) {
RepoDetailActivity.mViewPager.setCurrentItem(2);
}
else if(goToSectionType.equals("pull")) {
RepoDetailActivity.mViewPager.setCurrentItem(3);
}
}
checkRepositoryStarStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);
checkRepositoryWatchStatus(instanceUrl, Authorization.returnAuthentication(ctx, loginUid, instanceToken), repositoryOwner, repositoryName);

View File

@ -0,0 +1,94 @@
package org.mian.gitnex.activities;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
import org.mian.gitnex.R;
import org.mian.gitnex.databinding.ActivitySettingsGeneralBinding;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.helpers.Toasty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author M M Arif
*/
public class SettingsGeneralActivity extends BaseActivity {
private ActivitySettingsGeneralBinding viewBinding;
private Context appCtx;
private View.OnClickListener onClickListener;
private List<String> defaultScreen;
private static int defaultScreenSelectedChoice = 0;
@Override
protected int getLayoutResourceId() {
return R.layout.activity_settings_general;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appCtx = getApplicationContext();
viewBinding = ActivitySettingsGeneralBinding.inflate(getLayoutInflater());
View view = viewBinding.getRoot();
setContentView(view);
TinyDB tinyDb = new TinyDB(appCtx);
initCloseListener();
viewBinding.close.setOnClickListener(onClickListener);
String[] defaultScreen_ = {getResources().getString(R.string.generalDeepLinkSelectedText), getResources().getString(R.string.navRepos), getResources().getString(R.string.navOrgs), getResources().getString(R.string.pageTitleNotifications), getResources().getString(R.string.navExplore)};
defaultScreen = new ArrayList<>(Arrays.asList(defaultScreen_));
String[] linksArray = new String[defaultScreen.size()];
defaultScreen.toArray(linksArray);
if(!tinyDb.getString("defaultScreenStr").isEmpty()) {
viewBinding.generalDeepLinkSelected.setText(tinyDb.getString("defaultScreenStr"));
}
if(defaultScreenSelectedChoice == 0) {
defaultScreenSelectedChoice = tinyDb.getInt("defaultScreenId");
}
viewBinding.setDefaultLinkHandler.setOnClickListener(setDefaultLinkHandler -> {
AlertDialog.Builder dlBuilder = new AlertDialog.Builder(SettingsGeneralActivity.this);
dlBuilder.setTitle(R.string.linkSelectorDialogTitle);
if(defaultScreenSelectedChoice != -1) {
dlBuilder.setCancelable(true);
}
else {
dlBuilder.setCancelable(false);
}
dlBuilder.setSingleChoiceItems(linksArray, defaultScreenSelectedChoice, (dialogInterfaceHomeScreen, i) -> {
defaultScreenSelectedChoice = i;
viewBinding.generalDeepLinkSelected.setText(linksArray[i]);
tinyDb.putString("defaultScreenStr", linksArray[i]);
tinyDb.putInt("defaultScreenId", i);
dialogInterfaceHomeScreen.dismiss();
Toasty.success(appCtx, getResources().getString(R.string.settingsSave));
});
AlertDialog dlDialog = dlBuilder.create();
dlDialog.show();
});
}
private void initCloseListener() { onClickListener = view -> finish(); }
}

View File

@ -50,7 +50,7 @@ public class DraftsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsRepository, e.toString());
Log.e(StaticGlobalVariables.draftsApi, e.toString());
}
return draftId;
@ -66,7 +66,7 @@ public class DraftsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsRepository, e.toString());
Log.e(StaticGlobalVariables.draftsApi, e.toString());
}
return draftId;
@ -82,7 +82,7 @@ public class DraftsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.draftsRepository, e.toString());
Log.e(StaticGlobalVariables.draftsApi, e.toString());
}
return checkDraftFlag;

View File

@ -47,7 +47,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesRepository, e.toString());
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
}
return repositoryId;
@ -63,7 +63,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesRepository, e.toString());
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
}
return repository;
@ -89,7 +89,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesRepository, e.toString());
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
}
return checkRepository;
@ -105,7 +105,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesRepository, e.toString());
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
}
return repository;
@ -121,7 +121,7 @@ public class RepositoriesApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.repositoriesRepository, e.toString());
Log.e(StaticGlobalVariables.repositoriesApi, e.toString());
}
return repository;

View File

@ -17,6 +17,7 @@ public class UserAccountsApi {
private static UserAccountsDao userAccountsDao;
private static UserAccount userAccount;
private static List<UserAccount> userAccounts;
private static Integer checkAccount;
private static long accountId;
@ -49,7 +50,7 @@ public class UserAccountsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.userAccountsRepository, e.toString());
Log.e(StaticGlobalVariables.userAccountsApi, e.toString());
}
return accountId;
@ -80,7 +81,7 @@ public class UserAccountsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.userAccountsRepository, e.toString());
Log.e(StaticGlobalVariables.userAccountsApi, e.toString());
}
return userAccount;
@ -96,7 +97,7 @@ public class UserAccountsApi {
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.userAccountsRepository, e.toString());
Log.e(StaticGlobalVariables.userAccountsApi, e.toString());
}
return checkAccount;
@ -107,6 +108,22 @@ public class UserAccountsApi {
return userAccountsDao.fetchAllAccounts();
}
public List<UserAccount> usersAccounts() {
try {
Thread thread = new Thread(() -> userAccounts = userAccountsDao.userAccounts());
thread.start();
thread.join();
}
catch(InterruptedException e) {
Log.e(StaticGlobalVariables.userAccountsApi, e.toString());
}
return userAccounts;
}
public void deleteAccount(final int accountId) {
new Thread(() -> userAccountsDao.deleteAccount(accountId)).start();

View File

@ -20,6 +20,9 @@ public interface UserAccountsDao {
@Query("SELECT * FROM UserAccounts ORDER BY accountId ASC")
LiveData<List<UserAccount>> fetchAllAccounts();
@Query("SELECT * FROM UserAccounts ORDER BY accountId ASC")
List<UserAccount> userAccounts();
@Query("SELECT COUNT(accountId) FROM UserAccounts WHERE accountName = :accountName")
Integer getCount(String accountName);

View File

@ -20,6 +20,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.adapters.DraftsAdapter;
import org.mian.gitnex.database.api.DraftsApi;
import org.mian.gitnex.database.models.DraftWithRepository;
@ -51,6 +52,8 @@ public class DraftsFragment extends Fragment {
ctx = getContext();
setHasOptionsMenu(true);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.titleDrafts));
TinyDB tinyDb = new TinyDB(ctx);
draftsList_ = new ArrayList<>();

View File

@ -15,9 +15,7 @@ import android.view.inputmethod.EditorInfo;
import android.widget.ProgressBar;
import android.widget.TextView;
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;
@ -26,14 +24,12 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CreateRepoActivity;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.adapters.MyReposListAdapter;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.viewmodels.MyRepositoriesViewModel;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
@ -82,7 +78,7 @@ public class MyRepositoriesFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(requireContext());
final View v = inflater.inflate(R.layout.fragment_my_repositories, container, false);
setHasOptionsMenu(true);
@ -96,6 +92,8 @@ public class MyRepositoriesFragment extends Fragment {
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navMyRepos));
noDataMyRepo = v.findViewById(R.id.noDataMyRepo);
mProgressBar = v.findViewById(R.id.progress_bar);
mRecyclerView = v.findViewById(R.id.recyclerView);
@ -164,29 +162,28 @@ public class MyRepositoriesFragment extends Fragment {
MyRepositoriesViewModel myRepoModel = new ViewModelProvider(this).get(MyRepositoriesViewModel.class);
myRepoModel.getCurrentUserRepositories(instanceUrl, instanceToken, userLogin, getContext(), pageSize, resultLimit).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> myReposListMain) {
adapter = new MyReposListAdapter(getContext(), myReposListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noDataMyRepo.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
noDataMyRepo.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
}
});
myRepoModel.getCurrentUserRepositories(instanceUrl, instanceToken, userLogin, getContext(), pageSize, resultLimit).observe(getViewLifecycleOwner(),
myReposListMain -> {
adapter = new MyReposListAdapter(getContext(), myReposListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noDataMyRepo.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
noDataMyRepo.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(requireContext());
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);

View File

@ -16,7 +16,6 @@ import android.widget.TextView;
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;
@ -25,14 +24,12 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CreateOrganizationActivity;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.adapters.OrganizationsListAdapter;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserOrganizations;
import org.mian.gitnex.viewmodels.OrganizationListViewModel;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
@ -53,7 +50,7 @@ public class OrganizationsFragment extends Fragment {
final View v = inflater.inflate(R.layout.fragment_organizations, container, false);
setHasOptionsMenu(true);
boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(requireContext());
TinyDB tinyDb = new TinyDB(getContext());
final String instanceUrl = tinyDb.getString("instanceUrl");
@ -62,6 +59,8 @@ public class OrganizationsFragment extends Fragment {
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navOrgs));
mProgressBar = v.findViewById(R.id.progress_bar);
noDataOrg = v.findViewById(R.id.noDataOrg);
mRecyclerView = v.findViewById(R.id.recyclerView);
@ -74,14 +73,10 @@ public class OrganizationsFragment extends Fragment {
createNewOrganization = v.findViewById(R.id.addNewOrganization);
createNewOrganization.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), CreateOrganizationActivity.class);
startActivity(intent);
}
createNewOrganization.setOnClickListener(view -> {
Intent intent = new Intent(view.getContext(), CreateOrganizationActivity.class);
startActivity(intent);
});
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@ -131,21 +126,19 @@ public class OrganizationsFragment extends Fragment {
OrganizationListViewModel orgModel = new ViewModelProvider(this).get(OrganizationListViewModel.class);
orgModel.getUserOrgs(instanceUrl, instanceToken, getContext()).observe(getViewLifecycleOwner(), new Observer<List<UserOrganizations>>() {
@Override
public void onChanged(@Nullable List<UserOrganizations> orgsListMain) {
adapter = new OrganizationsListAdapter(getContext(), orgsListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noDataOrg.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
noDataOrg.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
orgModel.getUserOrgs(instanceUrl, instanceToken, getContext()).observe(getViewLifecycleOwner(), orgsListMain -> {
adapter = new OrganizationsListAdapter(getContext(), orgsListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noDataOrg.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
noDataOrg.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
});
}
@ -153,7 +146,7 @@ public class OrganizationsFragment extends Fragment {
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(requireContext());
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);

View File

@ -28,7 +28,6 @@ import org.mian.gitnex.helpers.ColorInverter;
import org.mian.gitnex.helpers.RoundedTransformation;
import org.mian.gitnex.helpers.TinyDB;
import java.util.Locale;
import java.util.Objects;
import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
@ -49,6 +48,8 @@ public class ProfileFragment extends Fragment {
View v = inflater.inflate(R.layout.fragment_profile, container, false);
setHasOptionsMenu(true);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navProfile));
TinyDB tinyDb = new TinyDB(getContext());
BlurView blurView = v.findViewById(R.id.blurView);
@ -123,15 +124,15 @@ public class ProfileFragment extends Fragment {
switch(tinyDb.getInt("customFontId", -1)) {
case 0:
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getContext()).getAssets(), "fonts/roboto.ttf");
myTypeface = Typeface.createFromAsset(requireContext().getAssets(), "fonts/roboto.ttf");
break;
case 2:
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getContext()).getAssets(), "fonts/sourcecodeproregular.ttf");
myTypeface = Typeface.createFromAsset(requireContext().getAssets(), "fonts/sourcecodeproregular.ttf");
break;
default:
myTypeface = Typeface.createFromAsset(Objects.requireNonNull(getContext()).getAssets(), "fonts/manroperegular.ttf");
myTypeface = Typeface.createFromAsset(requireContext().getAssets(), "fonts/manroperegular.ttf");
break;
}
@ -203,7 +204,7 @@ public class ProfileFragment extends Fragment {
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
menu.clear();
Objects.requireNonNull(getActivity()).getMenuInflater().inflate(R.menu.profile_dotted_menu, menu);
requireActivity().getMenuInflater().inflate(R.menu.profile_dotted_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}

View File

@ -16,7 +16,6 @@ import android.widget.TextView;
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;
@ -25,14 +24,12 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CreateRepoActivity;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.adapters.ReposListAdapter;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.viewmodels.RepositoriesListViewModel;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
@ -52,7 +49,7 @@ public class RepositoriesFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(requireContext());
final View v = inflater.inflate(R.layout.fragment_repositories, container, false);
setHasOptionsMenu(true);
@ -64,6 +61,8 @@ public class RepositoriesFragment extends Fragment {
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navRepos));
noDataRepo = v.findViewById(R.id.noData);
mProgressBar = v.findViewById(R.id.progress_bar);
mRecyclerView = v.findViewById(R.id.recyclerView);
@ -130,29 +129,28 @@ public class RepositoriesFragment extends Fragment {
RepositoriesListViewModel repoModel = new ViewModelProvider(this).get(RepositoriesListViewModel.class);
repoModel.getUserRepositories(instanceUrl, instanceToken, getContext(), pageSize, resultLimit).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> reposListMain) {
adapter = new ReposListAdapter(getContext(), reposListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noDataRepo.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
noDataRepo.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
}
});
repoModel.getUserRepositories(instanceUrl, instanceToken, getContext(), pageSize, resultLimit).observe(getViewLifecycleOwner(),
reposListMain -> {
adapter = new ReposListAdapter(getContext(), reposListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noDataRepo.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
noDataRepo.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(requireContext());
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);

View File

@ -12,9 +12,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.activities.SettingsAppearanceActivity;
import org.mian.gitnex.activities.SettingsDraftsActivity;
import org.mian.gitnex.activities.SettingsFileViewerActivity;
import org.mian.gitnex.activities.SettingsGeneralActivity;
import org.mian.gitnex.activities.SettingsReportsActivity;
import org.mian.gitnex.activities.SettingsSecurityActivity;
import org.mian.gitnex.activities.SettingsTranslationActivity;
@ -32,6 +34,9 @@ public class SettingsFragment extends Fragment {
View v = inflater.inflate(R.layout.fragment_settings, container, false);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navSettings));
LinearLayout generalFrame = v.findViewById(R.id.generalFrame);
LinearLayout appearanceFrame = v.findViewById(R.id.appearanceFrame);
LinearLayout fileViewerFrame = v.findViewById(R.id.fileViewerFrame);
LinearLayout draftsFrame = v.findViewById(R.id.draftsFrame);
@ -41,6 +46,8 @@ public class SettingsFragment extends Fragment {
LinearLayout rateAppFrame = v.findViewById(R.id.rateAppFrame);
LinearLayout aboutAppFrame = v.findViewById(R.id.aboutAppFrame);
generalFrame.setOnClickListener(generalFrameCall -> startActivity(new Intent(getContext(), SettingsGeneralActivity.class)));
appearanceFrame.setOnClickListener(v1 -> startActivity(new Intent(getContext(), SettingsAppearanceActivity.class)));
fileViewerFrame.setOnClickListener(v1 -> startActivity(new Intent(getContext(), SettingsFileViewerActivity.class)));

View File

@ -15,9 +15,7 @@ import android.view.inputmethod.EditorInfo;
import android.widget.ProgressBar;
import android.widget.TextView;
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;
@ -26,14 +24,12 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.CreateRepoActivity;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.adapters.StarredReposListAdapter;
import org.mian.gitnex.helpers.AppUtil;
import org.mian.gitnex.helpers.Authorization;
import org.mian.gitnex.helpers.TinyDB;
import org.mian.gitnex.models.UserRepositories;
import org.mian.gitnex.viewmodels.StarredRepositoriesViewModel;
import java.util.List;
import java.util.Objects;
/**
* Author M M Arif
@ -79,7 +75,7 @@ public class StarredRepositoriesFragment extends Fragment {
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_starred_repositories, container, false);
boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(requireContext());
setHasOptionsMenu(true);
TinyDB tinyDb = new TinyDB(getContext());
@ -89,6 +85,8 @@ public class StarredRepositoriesFragment extends Fragment {
final SwipeRefreshLayout swipeRefresh = v.findViewById(R.id.pullToRefresh);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navStarredRepos));
noData = v.findViewById(R.id.noData);
mProgressBar = v.findViewById(R.id.progress_bar);
mRecyclerView = v.findViewById(R.id.recyclerView);
@ -159,29 +157,28 @@ public class StarredRepositoriesFragment extends Fragment {
StarredRepositoriesViewModel starredRepoModel = new ViewModelProvider(this).get(StarredRepositoriesViewModel.class);
starredRepoModel.getUserStarredRepositories(instanceUrl, instanceToken, getContext(), pageSize, resultLimit).observe(getViewLifecycleOwner(), new Observer<List<UserRepositories>>() {
@Override
public void onChanged(@Nullable List<UserRepositories> starredReposListMain) {
adapter = new StarredReposListAdapter(getContext(), starredReposListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
}
});
starredRepoModel.getUserStarredRepositories(instanceUrl, instanceToken, getContext(), pageSize, resultLimit).observe(getViewLifecycleOwner(),
starredReposListMain -> {
adapter = new StarredReposListAdapter(getContext(), starredReposListMain);
if(adapter.getItemCount() > 0) {
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.GONE);
}
else {
adapter.notifyDataSetChanged();
mRecyclerView.setAdapter(adapter);
noData.setVisibility(View.VISIBLE);
}
mProgressBar.setVisibility(View.GONE);
});
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
boolean connToInternet = AppUtil.hasNetworkConnection(Objects.requireNonNull(getContext()));
boolean connToInternet = AppUtil.hasNetworkConnection(requireContext());
inflater.inflate(R.menu.search_menu, menu);
super.onCreateOptionsMenu(menu, inflater);

View File

@ -16,6 +16,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import org.mian.gitnex.R;
import org.mian.gitnex.activities.AddNewAccountActivity;
import org.mian.gitnex.activities.MainActivity;
import org.mian.gitnex.adapters.UserAccountsAdapter;
import org.mian.gitnex.database.api.UserAccountsApi;
import org.mian.gitnex.database.models.UserAccount;
@ -43,6 +44,8 @@ public class UserAccountsFragment extends Fragment {
ctx = getContext();
setHasOptionsMenu(true);
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.pageTitleUserAccounts));
userAccountsList = new ArrayList<>();
userAccountsApi = new UserAccountsApi(ctx);

View File

@ -25,11 +25,11 @@ public abstract class StaticGlobalVariables {
public static String tagPullRequestsList = "PullRequestsListFragment";
public static String tagIssuesList = "IssuesListFragment";
public static String tagMilestonesAdapter = "MilestonesAdapter";
public static String draftsRepository = "DraftsRepository";
public static String repositoriesRepository = "RepositoriesRepository";
public static String draftsApi = "DraftsApi";
public static String repositoriesApi = "RepositoriesApi";
public static String replyToIssueActivity = "ReplyToIssueActivity";
public static String tagDraftsBottomSheet = "BottomSheetDraftsFragment";
public static String userAccountsRepository = "UserAccountsRepository";
public static String userAccountsApi = "UserAccountsApi";
// issues variables
public static int issuesPageInit = 1;

View File

@ -58,6 +58,9 @@ import retrofit2.http.Query;
public interface ApiInterface {
@GET("version") // gitea version API without any auth
Call<GiteaVersion> getGiteaVersion();
@GET("version") // gitea version API
Call<GiteaVersion> getGiteaVersionWithBasic(@Header("Authorization") String authorization);
@ -331,6 +334,9 @@ public interface ApiInterface {
@POST("repos/{owner}/{repo}/pulls") // create a pull request
Call<ResponseBody> createPullRequest(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Body CreatePullRequest jsonStr);
@GET("repos/{owner}/{repo}/pulls/{index}") // get pull request by index
Call<PullRequests> getPullRequestByIndex(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Path("index") int index);
@GET("repos/{owner}/{repo}/commits") // get all commits
Call<List<Commits>> getRepositoryCommits(@Header("Authorization") String token, @Path("owner") String owner, @Path("repo") String repo, @Query("page") int page, @Query("sha") String branchName, @Query("limit") int limit);

View File

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="?attr/primaryBackgroundColor"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<com.google.android.material.progressindicator.ProgressIndicator
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Indeterminate"
android:layout_centerInParent="true"
app:indicatorColor="?attr/progressIndicatorColor" />
<LinearLayout
android:id="@+id/addNewAccountFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="32dp"
android:paddingBottom="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:visibility="gone"
android:orientation="vertical">
<TextView
android:id="@+id/addAccountText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/accountDoesNotExist"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<Button
android:id="@+id/addNewAccount"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/addNewAccountText"
android:textColor="@color/btnTextColor"
android:textSize="16sp"
android:layout_marginTop="24dp" />
<Button
android:id="@+id/openInBrowser"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/openWebRepo"
android:textColor="@color/btnTextColor"
android:textSize="16sp"
android:layout_marginTop="8dp" />
<Button
android:id="@+id/launchApp"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/launchApp"
android:textColor="@color/btnTextColor"
android:textSize="16sp"
android:layout_marginTop="8dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/noActionFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="32dp"
android:paddingBottom="16dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:visibility="gone"
android:orientation="vertical">
<TextView
android:id="@+id/noActionText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/noActionText"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
<Button
android:id="@+id/repository"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/navRepos"
android:textColor="@color/btnTextColor"
android:textSize="16sp"
android:layout_marginTop="24dp" />
<Button
android:id="@+id/organization"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/navOrgs"
android:textColor="@color/btnTextColor"
android:textSize="16sp"
android:layout_marginTop="8dp" />
<Button
android:id="@+id/notification"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/pageTitleNotifications"
android:textColor="@color/btnTextColor"
android:textSize="16sp"
android:layout_marginTop="8dp" />
<Button
android:id="@+id/explore"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/navExplore"
android:textColor="@color/btnTextColor"
android:textSize="16sp"
android:layout_marginTop="8dp" />
<Button
android:id="@+id/launchApp2"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="@string/launchApp"
android:textColor="@color/btnTextColor"
android:textSize="16sp"
android:layout_marginTop="8dp" />
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layoutReportingView"
android:orientation="vertical"
android:background="?attr/primaryBackgroundColor">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Widget.AppCompat.SearchView">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBackgroundColor"
android:theme="@style/AppTheme.AppBarOverlay">
<ImageView
android:id="@+id/close"
android:layout_width="@dimen/close_button_size"
android:layout_height="@dimen/close_button_size"
android:layout_marginRight="15dp"
android:layout_marginLeft="15dp"
android:gravity="center_vertical"
android:contentDescription="@string/close"
android:src="@drawable/ic_close" />
<TextView
android:id="@+id/toolbarTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/settingsGeneralHeader"
android:textColor="?attr/primaryTextColor"
android:maxLines="1"
android:textSize="20sp" />
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="@+id/setDefaultLinkHandler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="vertical">
<TextView
android:id="@+id/generalDeepLinkDefaultScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:layout_marginTop="10dp"
android:layout_marginStart="44dp"
android:layout_marginEnd="24dp"
android:text="@string/generalDeepLinkDefaultScreen"
android:textColor="?attr/primaryTextColor"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="44dp"
android:layout_marginEnd="44dp"
android:text="@string/generalDeepLinkDefaultScreenHintText"
android:textSize="12sp"
android:textColor="?attr/hintColor" />
<TextView
android:id="@+id/generalDeepLinkSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginStart="44dp"
android:layout_marginEnd="24dp"
android:text="@string/generalDeepLinkSelectedText"
android:textColor="?attr/selectedTextColor"/>
</LinearLayout>
</LinearLayout>

View File

@ -34,7 +34,7 @@
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:textStyle="bold"
android:drawableStart="@drawable/ic_person_add"
app:drawableStartCompat="@drawable/ic_person_add"
android:drawablePadding="16dp"
android:text="@string/newIssueSelectAssigneesListTitle" />

View File

@ -2,6 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/shape_custom_dialog"
android:orientation="vertical">
@ -25,7 +26,7 @@
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:textStyle="bold"
android:drawableStart="@drawable/ic_filter"
app:drawableStartCompat="@drawable/ic_filter"
android:drawablePadding="16dp"
android:text="@string/exploreFilterDialogTitle"
android:layout_marginBottom="4dp" />

View File

@ -34,7 +34,7 @@
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:textStyle="bold"
android:drawableStart="@drawable/ic_label"
app:drawableStartCompat="@drawable/ic_label"
android:drawablePadding="16dp"
android:text="@string/newIssueSelectLabelsListTitle" />

View File

@ -20,7 +20,7 @@
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:textStyle="bold"
android:drawableStart="@drawable/ic_delete"
app:drawableStartCompat="@drawable/ic_delete"
android:drawablePadding="16dp"
android:text="@string/repoSettingsDelete"
android:layout_marginBottom="16dp" />

View File

@ -21,7 +21,7 @@
android:textColor="?attr/primaryTextColor"
android:textSize="20sp"
android:textStyle="bold"
android:drawableStart="@drawable/ic_arrow_up"
app:drawableStartCompat="@drawable/ic_arrow_up"
android:drawablePadding="16dp"
android:text="@string/repoSettingsTransferOwnership"
android:layout_marginBottom="16dp" />

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBackgroundColor">
@ -17,23 +18,55 @@
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/appearanceFrame"
android:id="@+id/generalFrame"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<TextView
android:id="@+id/tvGeneral"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="24dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text="@string/settingsGeneralHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp"
app:drawableStartCompat="@drawable/ic_otp" />
<TextView
android:id="@+id/generalHintText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="60dp"
android:paddingEnd="12dp"
android:text="@string/generalHintText"
android:textColor="?attr/primaryTextColor"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/appearanceFrame"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_marginTop="25dp">
<TextView
android:id="@+id/tvAppearance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_appearance"
android:drawablePadding="24dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text="@string/settingsAppearanceHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
android:textSize="16sp"
app:drawableStartCompat="@drawable/ic_appearance" />
<TextView
android:id="@+id/appearanceHintText"
@ -59,13 +92,13 @@
android:id="@+id/fileViewer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_file"
android:drawablePadding="24dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text="@string/fileViewerHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
android:textSize="16sp"
app:drawableStartCompat="@drawable/ic_file" />
<TextView
android:id="@+id/fileViewerHintText"
@ -91,13 +124,13 @@
android:id="@+id/draftsHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_drafts"
android:drawablePadding="24dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text="@string/draftsHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
android:textSize="16sp"
app:drawableStartCompat="@drawable/ic_drafts" />
<TextView
android:id="@+id/draftsHintText"
@ -123,13 +156,13 @@
android:id="@+id/tvSecurity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_security"
android:drawablePadding="24dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text="@string/settingsSecurityHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
android:textSize="16sp"
app:drawableStartCompat="@drawable/ic_security" />
<TextView
android:id="@+id/securityHintText"
@ -155,13 +188,13 @@
android:id="@+id/tvLanguages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_flag"
android:drawablePadding="24dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text="@string/settingsLanguageHeaderText"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
android:textSize="16sp"
app:drawableStartCompat="@drawable/ic_flag" />
<TextView
android:id="@+id/languagesHintText"
@ -187,13 +220,13 @@
android:id="@+id/appReports"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_bug_report"
android:drawablePadding="24dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text="@string/reportViewerHeader"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
android:textSize="16sp"
app:drawableStartCompat="@drawable/ic_bug_report" />
<TextView
android:id="@+id/reportsHintText"
@ -245,19 +278,20 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="25dp">
android:layout_marginTop="25dp"
android:layout_marginBottom="20dp">
<TextView
android:id="@+id/aboutApp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_info"
android:drawablePadding="24dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text="@string/navAbout"
android:textColor="?attr/primaryTextColor"
android:textSize="16sp" />
android:textSize="16sp"
app:drawableStartCompat="@drawable/ic_info" />
<TextView
android:id="@+id/aboutAppHintText"

View File

@ -270,6 +270,12 @@
<string name="draftsHintText">Comments draft</string>
<string name="settingsEnableCommentsDeletionText">Enable Drafts Deletion</string>
<string name="settingsEnableCommentsDeletionHintText">Delete comment draft when comment is posted</string>
<string name="settingsGeneralHeader">General</string>
<string name="generalHintText">Default actions</string>
<string name="generalDeepLinkDefaultScreen">Default Link Handler</string>
<string name="generalDeepLinkDefaultScreenHintText">Choose what screen should be loaded if the app cannot handle external links. It will redirect you automatically.</string>
<string name="generalDeepLinkSelectedText">N/A</string>
<string name="linkSelectorDialogTitle">Select Default Screen</string>
<!-- settings -->
<string name="noMoreData">No more data available</string>
@ -716,4 +722,8 @@
<string name="prCreateSuccess">Pull Request created successfully</string>
<string name="prAlreadyExists">A pull request between these branches already exists</string>
<string name="accountDoesNotExist">It seems that account for URI %1$s does not exists in the app. You can add one by tapping on the Add New Account button.</string>
<string name="launchApp">Go to App</string>
<string name="noActionText">GitNex cannot handle the requested resource, you can open an issue at the project repository as an improvement with providing details of the work. Just launch a default screen for now from the buttons below, it can be changed from settings.</string>
</resources>

View File

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
classpath 'com.android.tools.build:gradle:4.1.0'
}
}

View File

@ -1,6 +1,6 @@
#Mon Jun 08 18:15:01 CEST 2020
#Fri Oct 16 14:46:05 SGT 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip