From 23bd6f3201f8b82bdca1631f555d39158ef8b39f Mon Sep 17 00:00:00 2001 From: M M Arif Date: Mon, 7 Apr 2025 20:35:56 +0500 Subject: [PATCH] Improve changelog UI, add where to get access token --- .../activities/AddNewAccountActivity.java | 37 ++++ .../mian/gitnex/activities/LoginActivity.java | 37 ++++ .../mian/gitnex/activities/MainActivity.java | 4 +- .../org/mian/gitnex/helpers/ChangeLog.java | 204 ++++++++++++++---- .../res/layout/activity_add_new_account.xml | 10 + app/src/main/res/layout/activity_login.xml | 11 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/changelog.xml | 4 +- 8 files changed, 258 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/org/mian/gitnex/activities/AddNewAccountActivity.java b/app/src/main/java/org/mian/gitnex/activities/AddNewAccountActivity.java index b8627961..e37c791e 100644 --- a/app/src/main/java/org/mian/gitnex/activities/AddNewAccountActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/AddNewAccountActivity.java @@ -4,8 +4,12 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.os.Handler; +import android.util.TypedValue; import android.widget.ArrayAdapter; +import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.core.text.HtmlCompat; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import io.mikael.urlbuilder.UrlBuilder; import java.net.URI; @@ -61,6 +65,8 @@ public class AddNewAccountActivity extends BaseActivity { spinnerSelectedValue = Protocol.HTTPS.toString(); } + viewBinding.tokenHelper.setOnClickListener(token -> showTokenHelpDialog()); + ArrayAdapter adapterProtocols = new ArrayAdapter<>(ctx, R.layout.list_spinner_items, Protocol.values()); @@ -84,6 +90,37 @@ public class AddNewAccountActivity extends BaseActivity { }); } + private void showTokenHelpDialog() { + + MaterialAlertDialogBuilder dialogBuilder = + new MaterialAlertDialogBuilder(this) + .setMessage( + HtmlCompat.fromHtml( + getString(R.string.where_to_get_token_message), + HtmlCompat.FROM_HTML_MODE_LEGACY)) + .setPositiveButton(R.string.close, null) + .setCancelable(true); + + AlertDialog dialog = dialogBuilder.create(); + dialog.show(); + + TextView messageView = dialog.findViewById(android.R.id.message); + if (messageView != null) { + messageView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); + int paddingTop = + (int) + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 16, + getResources().getDisplayMetrics()); + messageView.setPadding( + messageView.getPaddingLeft(), + paddingTop, + messageView.getPaddingRight(), + messageView.getPaddingBottom()); + } + } + private void processLogin() { try { 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 5ebf8038..b4931ab8 100644 --- a/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/LoginActivity.java @@ -10,10 +10,14 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.util.TypedValue; import android.widget.ArrayAdapter; +import android.widget.TextView; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.core.text.HtmlCompat; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import io.mikael.urlbuilder.UrlBuilder; import java.io.File; @@ -93,6 +97,8 @@ public class LoginActivity extends BaseActivity { disableProcessButton(); } + activityLoginBinding.tokenHelper.setOnClickListener(token -> showTokenHelpDialog()); + networkStatusObserver.registerNetworkStatusListener( hasNetworkConnection -> runOnUiThread( @@ -138,6 +144,37 @@ public class LoginActivity extends BaseActivity { }); } + private void showTokenHelpDialog() { + + MaterialAlertDialogBuilder dialogBuilder = + new MaterialAlertDialogBuilder(this) + .setMessage( + HtmlCompat.fromHtml( + getString(R.string.where_to_get_token_message), + HtmlCompat.FROM_HTML_MODE_LEGACY)) + .setPositiveButton(R.string.close, null) + .setCancelable(true); + + AlertDialog dialog = dialogBuilder.create(); + dialog.show(); + + TextView messageView = dialog.findViewById(android.R.id.message); + if (messageView != null) { + messageView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); + int paddingTop = + (int) + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 16, + getResources().getDisplayMetrics()); + messageView.setPadding( + messageView.getPaddingLeft(), + paddingTop, + messageView.getPaddingRight(), + messageView.getPaddingBottom()); + } + } + private void login() { try { 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 b650cb02..c2036562 100644 --- a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java @@ -526,9 +526,7 @@ public class MainActivity extends BaseActivity if (versionCode > tinyDB.getInt("versionCode")) { tinyDB.putInt("versionCode", versionCode); - - ChangeLog changelogDialog = new ChangeLog(this); - changelogDialog.showDialog(); + new ChangeLog(this).showDialog(); } OnBackPressedCallback onBackPressedCallback = diff --git a/app/src/main/java/org/mian/gitnex/helpers/ChangeLog.java b/app/src/main/java/org/mian/gitnex/helpers/ChangeLog.java index 1e94058b..1d79c239 100644 --- a/app/src/main/java/org/mian/gitnex/helpers/ChangeLog.java +++ b/app/src/main/java/org/mian/gitnex/helpers/ChangeLog.java @@ -1,14 +1,21 @@ package org.mian.gitnex.helpers; import android.app.Activity; -import android.content.pm.PackageManager; import android.content.res.Resources; import android.content.res.XmlResourceParser; -import android.util.Log; +import android.util.TypedValue; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; import androidx.core.text.HtmlCompat; import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.vdurmont.emoji.EmojiParser; import java.io.IOException; -import java.util.Objects; +import java.util.ArrayList; +import java.util.List; import org.mian.gitnex.R; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -18,82 +25,185 @@ import org.xmlpull.v1.XmlPullParserException; */ public class ChangeLog { - private static final String TAG = "ChangeLog"; - private static final String CHANGELOG_XML_NODE = "changelog"; - private final Activity changelogActivity; public ChangeLog(Activity context) { - changelogActivity = context; + this.changelogActivity = context; } - private String ParseReleaseTag(XmlResourceParser aXml) - throws XmlPullParserException, IOException { + private static class Release { + String version; + int versioncode; + List types; - StringBuilder strBuilder = - new StringBuilder(aXml.getAttributeValue(null, "version") + "
"); - int eventType = aXml.getEventType(); - - while ((eventType != XmlPullParser.END_TAG) || (aXml.getName().equals("change"))) { - - if ((eventType == XmlPullParser.START_TAG) && (aXml.getName().equals("change"))) { - eventType = aXml.next(); - strBuilder.append(aXml.getText()).append("
"); - } - eventType = aXml.next(); + Release(String version, int versioncode) { + this.version = version; + this.versioncode = versioncode; + this.types = new ArrayList<>(); } - strBuilder.append("
"); - - return strBuilder.toString(); } - private String getChangelog(int resId, Resources res) { + private static class Type { + String name; + List changes; - StringBuilder strBuilder = new StringBuilder(); - try (XmlResourceParser xml = res.getXml(resId)) { + Type(String name) { + this.name = name; + this.changes = new ArrayList<>(); + } + } + private Release parseLatestRelease(@NonNull XmlResourceParser xml) { + + List releases = new ArrayList<>(); + Release currentRelease = null; + Type currentType = null; + + try { int eventType = xml.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { - if ((eventType == XmlPullParser.START_TAG) && (xml.getName().equals("release"))) { - strBuilder.append(ParseReleaseTag(xml)); + if (eventType == XmlPullParser.START_TAG) { + + String tagName = xml.getName(); + if (tagName.equals("release")) { + String version = xml.getAttributeValue(null, "version"); + int versioncode = xml.getAttributeIntValue(null, "versioncode", -1); + currentRelease = new Release(version, versioncode); + releases.add(currentRelease); + } else if (tagName.equals("type") && currentRelease != null) { + String typeName = xml.getAttributeValue(null, "name"); + currentType = new Type(typeName); + currentRelease.types.add(currentType); + } else if (tagName.equals("change") && currentType != null) { + eventType = xml.next(); + if (eventType == XmlPullParser.TEXT) { + String changeText = xml.getText().trim(); + if (!changeText.isEmpty()) { + currentType.changes.add(changeText); + } + } + } } eventType = xml.next(); } - } catch (XmlPullParserException | IOException e) { - Log.e(TAG, Objects.requireNonNull(e.getMessage())); + return new Release("Error", -1); } - return strBuilder.toString(); + Release latest = null; + for (Release r : releases) { + if (latest == null + || (r.versioncode > latest.versioncode && r.versioncode != -1) + || (r.versioncode == -1 && latest.versioncode == -1)) { + latest = r; + } + } + return latest != null ? latest : new Release("No releases found", -1); + } + + private LinearLayout buildChangelogView(Release release) { + + LinearLayout layout = new LinearLayout(changelogActivity); + layout.setOrientation(LinearLayout.VERTICAL); + int paddingHorizontal = + (int) + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 24, + changelogActivity.getResources().getDisplayMetrics()); + int paddingVertical = + (int) + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 16, + changelogActivity.getResources().getDisplayMetrics()); + layout.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical); + + TextView versionView = new TextView(changelogActivity); + versionView.setText( + HtmlCompat.fromHtml( + "" + release.version + "", HtmlCompat.FROM_HTML_MODE_LEGACY)); + versionView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18); + LinearLayout.LayoutParams versionParams = + new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + versionParams.setMargins(0, 0, 0, 16); + versionView.setLayoutParams(versionParams); + layout.addView(versionView); + + for (Type type : release.types) { + + TextView typeView = new TextView(changelogActivity); + typeView.setText( + HtmlCompat.fromHtml( + "" + EmojiParser.parseToUnicode(type.name) + "", + HtmlCompat.FROM_HTML_MODE_LEGACY)); + typeView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); + LinearLayout.LayoutParams typeParams = + new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + typeParams.setMargins(0, 48, 0, 16); + typeView.setLayoutParams(typeParams); + layout.addView(typeView); + + for (String change : type.changes) { + if (!change.isEmpty()) { + TextView changeView = new TextView(changelogActivity); + changeView.setText( + HtmlCompat.fromHtml("• " + change, HtmlCompat.FROM_HTML_MODE_LEGACY)); + changeView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); + LinearLayout.LayoutParams changeParams = + new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + changeParams.setMargins(32, 0, 0, 8); + changeView.setLayoutParams(changeParams); + layout.addView(changeView); + } + } + } + + return layout; } public void showDialog() { - String packageName = changelogActivity.getPackageName(); - Resources res = null; + Resources res = changelogActivity.getResources(); + Release latestRelease; - try { - res = changelogActivity.getPackageManager().getResourcesForApplication(packageName); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, Objects.requireNonNull(e.getMessage())); + try (XmlResourceParser xml = res.getXml(R.xml.changelog)) { + latestRelease = parseLatestRelease(xml); + } catch (Exception e) { + latestRelease = new Release("Error loading changelog", -1); } - assert res != null; - int resId = res.getIdentifier(CHANGELOG_XML_NODE, "xml", packageName); + ScrollView scrollView = new ScrollView(changelogActivity); + scrollView.addView(buildChangelogView(latestRelease)); - String changelogMessage = getChangelog(resId, res); - - MaterialAlertDialogBuilder materialAlertDialogBuilder = + MaterialAlertDialogBuilder dialogBuilder = new MaterialAlertDialogBuilder(changelogActivity) .setTitle(R.string.changelogTitle) - .setMessage( - HtmlCompat.fromHtml( - "" + changelogMessage + "", - HtmlCompat.FROM_HTML_MODE_LEGACY)) + .setView(scrollView) .setCancelable(false) .setNeutralButton(R.string.close, null); - materialAlertDialogBuilder.create().show(); + AlertDialog dialog = dialogBuilder.create(); + dialog.show(); + TextView titleView = dialog.findViewById(com.google.android.material.R.id.alertTitle); + if (titleView != null) { + int extraTopPadding = + (int) + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 16, + changelogActivity.getResources().getDisplayMetrics()); + titleView.setPadding( + titleView.getPaddingLeft(), + titleView.getPaddingTop() + extraTopPadding, + titleView.getPaddingRight(), + titleView.getPaddingBottom()); + } } } diff --git a/app/src/main/res/layout/activity_add_new_account.xml b/app/src/main/res/layout/activity_add_new_account.xml index 6082c0a4..31886cee 100644 --- a/app/src/main/res/layout/activity_add_new_account.xml +++ b/app/src/main/res/layout/activity_add_new_account.xml @@ -126,6 +126,16 @@ + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 5a0fe2b1..7965ad62 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -148,6 +148,17 @@ + + Support Patreon Feedback + Where can I get an access token? + • Log in to your account on your instance (Codeberg, etc.).
• Click on your user profile picture, then go to Settings.
• Under Applications, create a token with a name of your choice.
• Choose All (public, private, and limited).
• Under Select permissions, select Read and write for each dropdown.

Once created, copy and paste or type the token here along with the instance URL.]]>
My Repositories diff --git a/app/src/main/res/xml/changelog.xml b/app/src/main/res/xml/changelog.xml index 5b5b3a0f..8eb904ef 100644 --- a/app/src/main/res/xml/changelog.xml +++ b/app/src/main/res/xml/changelog.xml @@ -2,7 +2,9 @@ - Under development + + Under development +