From 30abcc3ce99b053b540aa9f6a68911af0b62e601 Mon Sep 17 00:00:00 2001 From: M M Arif Date: Thu, 17 Jul 2025 20:20:24 +0500 Subject: [PATCH] Implement instance providers on login and new account --- .../mian/gitnex/activities/LoginActivity.java | 86 +++++++++++++------ .../mian/gitnex/activities/MainActivity.java | 20 ++++- .../adapters/UserAccountsNavAdapter.java | 14 +-- .../gitnex/database/api/UserAccountsApi.java | 10 ++- .../gitnex/database/dao/UserAccountsDao.java | 5 +- .../gitnex/database/db/GitnexDatabase.java | 18 +++- .../gitnex/database/models/UserAccount.java | 11 ++- .../java/org/mian/gitnex/helpers/AppUtil.java | 9 ++ .../java/org/mian/gitnex/helpers/Version.java | 4 + .../helpers/contexts/AccountContext.java | 4 + app/src/main/res/layout/activity_login.xml | 23 +++++ app/src/main/res/values/settings.xml | 7 ++ app/src/main/res/values/strings.xml | 2 + 13 files changed, 168 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java b/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java index 1de7eb88..73fc00f8 100644 --- a/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java @@ -47,7 +47,7 @@ import retrofit2.Call; import retrofit2.Callback; /** - * @author M M Arif + * @author mmarif */ public class LoginActivity extends BaseActivity { @@ -59,8 +59,8 @@ public class LoginActivity extends BaseActivity { private int defaultPagingNumber = 25; private final String DATABASE_NAME = "gitnex"; private boolean hasShownInitialNetworkError = false; - private String mode; private int btnText; + private String selectedProvider = "gitea"; @Override public void onCreate(Bundle savedInstanceState) { @@ -70,12 +70,11 @@ public class LoginActivity extends BaseActivity { activityLoginBinding = ActivityLoginBinding.inflate(getLayoutInflater()); setContentView(activityLoginBinding.getRoot()); - mode = getIntent().getStringExtra("mode"); + String mode = getIntent().getStringExtra("mode"); if (mode == null) { mode = "login"; btnText = R.string.btnLogin; - } - else { + } else { btnText = R.string.addNewAccountText; } @@ -95,6 +94,10 @@ public class LoginActivity extends BaseActivity { new ArrayAdapter<>( LoginActivity.this, R.layout.list_spinner_items, Protocol.values()); + ArrayAdapter adapterProviders = + ArrayAdapter.createFromResource( + this, R.array.provider_options, R.layout.list_spinner_items); + activityLoginBinding.instanceUrl.setText(getIntent().getStringExtra("instanceUrl")); String scheme = getIntent().getStringExtra("scheme"); if (scheme != null && scheme.equals("http")) { @@ -110,7 +113,6 @@ public class LoginActivity extends BaseActivity { activityLoginBinding.httpsSpinner.setOnItemClickListener( (parent, view, position, id) -> { selectedProtocol = String.valueOf(parent.getItemAtPosition(position)); - if (selectedProtocol.equals(String.valueOf(Protocol.HTTP))) { SnackBar.warning( ctx, @@ -119,6 +121,17 @@ public class LoginActivity extends BaseActivity { } }); + activityLoginBinding.providerSpinner.setAdapter(adapterProviders); + activityLoginBinding.providerSpinner.setSelection(0); + activityLoginBinding.providerSpinner.setText(adapterProviders.getItem(0), false); + activityLoginBinding.providerSpinner.setOnItemClickListener( + (parent, view, position, id) -> { + selectedProvider = + position == 0 + ? "gitea" + : position == 1 || position == 2 ? "forgejo" : "infer"; + }); + if (AppUtil.hasNetworkConnection(ctx)) { enableProcessButton(); } else { @@ -135,8 +148,7 @@ public class LoginActivity extends BaseActivity { enableProcessButton(); } else { disableProcessButton(); - activityLoginBinding.loginButton.setText( - btnText); + activityLoginBinding.loginButton.setText(btnText); if (hasShownInitialNetworkError) { SnackBar.error( ctx, @@ -207,6 +219,15 @@ public class LoginActivity extends BaseActivity { try { + if (selectedProvider == null || selectedProvider.isEmpty()) { + SnackBar.error( + ctx, + findViewById(android.R.id.content), + getString(R.string.provider_empty_error)); + enableProcessButton(); + return; + } + if (selectedProtocol == null) { SnackBar.error( @@ -217,12 +238,32 @@ public class LoginActivity extends BaseActivity { return; } + if (Objects.requireNonNull(activityLoginBinding.instanceUrl.getText()) + .toString() + .isEmpty()) { + + SnackBar.error( + ctx, findViewById(android.R.id.content), getString(R.string.emptyFieldURL)); + enableProcessButton(); + return; + } + String loginToken = Objects.requireNonNull(activityLoginBinding.loginTokenCode.getText()) .toString() .replaceAll("[\\uFEFF|#]", "") .trim(); + if (loginToken.isEmpty()) { + + SnackBar.error( + ctx, + findViewById(android.R.id.content), + getString(R.string.loginTokenError)); + enableProcessButton(); + return; + } + URI rawInstanceUrl = UrlBuilder.fromString( UrlHelper.fixScheme( @@ -241,24 +282,6 @@ public class LoginActivity extends BaseActivity { .withPath(PathsHelper.join(rawInstanceUrl.getPath(), "/api/v1/")) .toUri(); - if (activityLoginBinding.instanceUrl.getText().toString().isEmpty()) { - - SnackBar.error( - ctx, findViewById(android.R.id.content), getString(R.string.emptyFieldURL)); - enableProcessButton(); - return; - } - - if (loginToken.isEmpty()) { - - SnackBar.error( - ctx, - findViewById(android.R.id.content), - getString(R.string.loginTokenError)); - enableProcessButton(); - return; - } - versionCheck(loginToken); serverPageLimitSettings(String.valueOf(instanceUrl), loginToken); @@ -333,6 +356,9 @@ public class LoginActivity extends BaseActivity { } giteaVersion = new Version(version.getVersion()); + if (selectedProvider.equals("infer")) { + selectedProvider = AppUtil.inferProvider(version.getVersion()); + } if (giteaVersion.less(getString(R.string.versionLow))) { @@ -434,11 +460,17 @@ public class LoginActivity extends BaseActivity { loginToken, giteaVersion.toString(), maxResponseItems, - defaultPagingNumber); + defaultPagingNumber, + selectedProvider); account = userAccountsApi.getAccountById((int) accountId); } else { userAccountsApi.updateTokenByAccountName( accountName, loginToken); + userAccountsApi.updateProvider( + selectedProvider, + userAccountsApi + .getAccountByName(accountName) + .getAccountId()); userAccountsApi.login( userAccountsApi .getAccountByName(accountName) diff --git a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java index 1b9626bf..afc0627f 100644 --- a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java @@ -4,7 +4,6 @@ import android.annotation.SuppressLint; import android.content.Intent; import android.os.Bundle; import android.os.Handler; -import android.text.Html; import android.util.TypedValue; import android.view.View; import android.widget.ImageView; @@ -12,6 +11,7 @@ import android.widget.TextView; import androidx.activity.EdgeToEdge; import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; +import androidx.core.text.HtmlCompat; import androidx.navigation.NavController; import androidx.navigation.NavOptions; import androidx.navigation.fragment.NavHostFragment; @@ -95,11 +95,23 @@ public class MainActivity extends BaseActivity return; } - if (tinyDB.getInt("currentActiveAccountId", -1) <= 0) { + int currentAccountId = tinyDB.getInt("currentActiveAccountId", -1); + if (currentAccountId <= 0) { AppUtil.logout(this); return; } + UserAccountsApi userAccountsApi = BaseApi.getInstance(this, UserAccountsApi.class); + if (userAccountsApi != null) { + UserAccount currentAccount = userAccountsApi.getAccountById(currentAccountId); + if (currentAccount != null + && (currentAccount.getProvider() == null + || currentAccount.getProvider().isEmpty())) { + String inferredProvider = AppUtil.inferProvider(currentAccount.getServerVersion()); + userAccountsApi.updateProvider(inferredProvider, currentAccountId); + } + } + setSupportActionBar(binding.toolbar); binding.toolbar.setVisibility(View.GONE); binding.toolbar.invalidate(); @@ -322,7 +334,9 @@ public class MainActivity extends BaseActivity ImageView userAvatar = binding.userAvatar; if (name != null && !name.isEmpty()) { - userFullname.setText(Html.fromHtml(name)); + userFullname.setText( + HtmlCompat.fromHtml( + name, HtmlCompat.FROM_HTML_MODE_LEGACY)); } else { userFullname.setText(username); } diff --git a/app/src/main/java/org/mian/gitnex/adapters/UserAccountsNavAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/UserAccountsNavAdapter.java index 0868b816..3bd835fd 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/UserAccountsNavAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/UserAccountsNavAdapter.java @@ -23,7 +23,7 @@ import org.mian.gitnex.database.models.UserAccount; import org.mian.gitnex.helpers.UrlHelper; /** - * @author M M Arif + * @author mmarif */ public class UserAccountsNavAdapter extends RecyclerView.Adapter { @@ -81,12 +81,12 @@ public class UserAccountsNavAdapter } newAccount.setOnClickListener( - item -> { - Intent intent = new Intent(context, LoginActivity.class); - intent.putExtra("mode", "new_account"); - context.startActivity(intent); - dialog.dismiss(); - }); + item -> { + Intent intent = new Intent(context, LoginActivity.class); + intent.putExtra("mode", "new_account"); + context.startActivity(intent); + dialog.dismiss(); + }); UserAccountsAdapter arrayAdapter = new UserAccountsAdapter(context, dialog); listView.setLayoutManager(new LinearLayoutManager(context)); diff --git a/app/src/main/java/org/mian/gitnex/database/api/UserAccountsApi.java b/app/src/main/java/org/mian/gitnex/database/api/UserAccountsApi.java index f010cf50..c85a732e 100644 --- a/app/src/main/java/org/mian/gitnex/database/api/UserAccountsApi.java +++ b/app/src/main/java/org/mian/gitnex/database/api/UserAccountsApi.java @@ -7,7 +7,7 @@ import org.mian.gitnex.database.dao.UserAccountsDao; import org.mian.gitnex.database.models.UserAccount; /** - * @author M M Arif + * @author mmarif */ public class UserAccountsApi extends BaseApi { @@ -25,7 +25,8 @@ public class UserAccountsApi extends BaseApi { String token, String serverVersion, int maxResponseItems, - int defaultPagingNumber) { + int defaultPagingNumber, + String provider) { UserAccount userAccount = new UserAccount(); userAccount.setAccountName(accountName); @@ -36,6 +37,7 @@ public class UserAccountsApi extends BaseApi { userAccount.setLoggedIn(true); userAccount.setMaxResponseItems(maxResponseItems); userAccount.setDefaultPagingNumber(defaultPagingNumber); + userAccount.setProvider(provider); return userAccountsDao.createAccount(userAccount); } @@ -117,4 +119,8 @@ public class UserAccountsApi extends BaseApi { public void login(int accountId) { executorService.execute(() -> userAccountsDao.login(accountId)); } + + public void updateProvider(final String provider, final int accountId) { + executorService.execute(() -> userAccountsDao.updateProvider(provider, accountId)); + } } diff --git a/app/src/main/java/org/mian/gitnex/database/dao/UserAccountsDao.java b/app/src/main/java/org/mian/gitnex/database/dao/UserAccountsDao.java index 21388fa2..199764ab 100644 --- a/app/src/main/java/org/mian/gitnex/database/dao/UserAccountsDao.java +++ b/app/src/main/java/org/mian/gitnex/database/dao/UserAccountsDao.java @@ -8,7 +8,7 @@ import java.util.List; import org.mian.gitnex.database.models.UserAccount; /** - * @author M M Arif + * @author mmarif */ @Dao public interface UserAccountsDao { @@ -81,4 +81,7 @@ public interface UserAccountsDao { @Query("DELETE FROM UserAccounts WHERE accountId = :accountId") void deleteAccount(int accountId); + + @Query("UPDATE UserAccounts SET provider = :provider WHERE accountId = :accountId") + void updateProvider(String provider, int accountId); } diff --git a/app/src/main/java/org/mian/gitnex/database/db/GitnexDatabase.java b/app/src/main/java/org/mian/gitnex/database/db/GitnexDatabase.java index d9fa92b3..b02386bb 100644 --- a/app/src/main/java/org/mian/gitnex/database/db/GitnexDatabase.java +++ b/app/src/main/java/org/mian/gitnex/database/db/GitnexDatabase.java @@ -17,11 +17,11 @@ import org.mian.gitnex.database.models.Repository; import org.mian.gitnex.database.models.UserAccount; /** - * @author M M Arif + * @author mmarif */ @Database( entities = {Repository.class, UserAccount.class, Notes.class, AppSettings.class}, - version = 10, + version = 11, exportSchema = false) public abstract class GitnexDatabase extends RoomDatabase { @@ -30,7 +30,6 @@ public abstract class GitnexDatabase extends RoomDatabase { new Migration(1, 2) { @Override public void migrate(@NonNull SupportSQLiteDatabase database) { - // database.execSQL("DROP TABLE Drafts"); database.execSQL("ALTER TABLE 'Drafts' ADD COLUMN 'commentId' TEXT"); } }; @@ -110,6 +109,16 @@ public abstract class GitnexDatabase extends RoomDatabase { database.execSQL("DROP table Drafts"); } }; + + private static final Migration MIGRATION_10_11 = + new Migration(10, 11) { + + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL("ALTER TABLE 'userAccounts' ADD COLUMN 'provider' TEXT"); + } + }; + private static volatile GitnexDatabase gitnexDatabase; public static GitnexDatabase getDatabaseInstance(Context context) { @@ -131,7 +140,8 @@ public abstract class GitnexDatabase extends RoomDatabase { MIGRATION_6_7, MIGRATION_7_8, MIGRATION_8_9, - MIGRATION_9_10) + MIGRATION_9_10, + MIGRATION_10_11) .build(); } } diff --git a/app/src/main/java/org/mian/gitnex/database/models/UserAccount.java b/app/src/main/java/org/mian/gitnex/database/models/UserAccount.java index c426cf41..2b6b0bb2 100644 --- a/app/src/main/java/org/mian/gitnex/database/models/UserAccount.java +++ b/app/src/main/java/org/mian/gitnex/database/models/UserAccount.java @@ -6,7 +6,7 @@ import androidx.room.PrimaryKey; import java.io.Serializable; /** - * @author M M Arif + * @author mmarif */ @Entity(tableName = "userAccounts") public class UserAccount implements Serializable { @@ -24,6 +24,7 @@ public class UserAccount implements Serializable { private int defaultPagingNumber; private int maxAttachmentsSize; private int maxNumberOfAttachments; + private String provider; public int getAccountId() { return accountId; @@ -112,4 +113,12 @@ public class UserAccount implements Serializable { public void setMaxNumberOfAttachments(int maxNumberOfAttachments) { this.maxNumberOfAttachments = maxNumberOfAttachments; } + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } } diff --git a/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java b/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java index 3e2fda59..2aa98158 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java +++ b/app/src/main/java/org/mian/gitnex/helpers/AppUtil.java @@ -721,4 +721,13 @@ public class AppUtil { } return resource; } + + public static String inferProvider(String version) { + if (Version.valid(version)) { + Version v = new Version(version); + int majorVersion = v.getValues().isEmpty() ? 0 : v.getValues().get(0); + return majorVersion == 1 ? "gitea" : "forgejo"; + } + return "gitea"; + } } diff --git a/app/src/main/java/org/mian/gitnex/helpers/Version.java b/app/src/main/java/org/mian/gitnex/helpers/Version.java index d6cf5128..bbbffe3e 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/Version.java +++ b/app/src/main/java/org/mian/gitnex/helpers/Version.java @@ -236,4 +236,8 @@ public class Version { return raw; } + + public List getValues() { + return values; + } } diff --git a/app/src/main/java/org/mian/gitnex/helpers/contexts/AccountContext.java b/app/src/main/java/org/mian/gitnex/helpers/contexts/AccountContext.java index 7a13eca1..8ec1fc6a 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/contexts/AccountContext.java +++ b/app/src/main/java/org/mian/gitnex/helpers/contexts/AccountContext.java @@ -83,4 +83,8 @@ public class AccountContext implements Serializable { assert account.getAccountName() != null; return new File(context.getCacheDir() + "responses", account.getAccountName()); } + + public String getProvider() { + return getAccount().getProvider(); + } } diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 422514da..893e0e62 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -65,6 +65,29 @@ android:orientation="vertical" android:padding="@dimen/dimen28dp"> + + + + + + zh-TW + + Gitea + Forgejo + Codeberg (Forgejo-based) + I am not sure + + Roboto Manrope diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b30be8ad..1e6b368a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1002,4 +1002,6 @@ Switch account Clear Cache (%1$s) Repository does not exist + Select instance provider + Please select an instance provider