Add sponsor badge next to own name on profile
- SponsorHelper queries FoxCloud /mobile/me by Telegram ID (X-Tg-Id) and caches is_sponsor per account - Self profile shows a sponsor badge next to the name when is_sponsor is true - Reactive refresh via new NotificationCenter.sponsorStatusUpdated global event Verified: TMessagesProj compileReleaseJavaWithJavac succeeds.
This commit is contained in:
parent
d200a290f8
commit
51bde550b9
5 changed files with 185 additions and 0 deletions
|
|
@ -279,6 +279,7 @@ public class NotificationCenter {
|
|||
public static final int updatedChatRanks = totalEvents++;
|
||||
public static final int joinedGroup = totalEvents++;
|
||||
public static final int loadedAiComposeTones = totalEvents++;
|
||||
public static final int sponsorStatusUpdated = totalEvents++;
|
||||
|
||||
//global
|
||||
public static final int pushMessagesUpdated = totalEvents++;
|
||||
|
|
|
|||
|
|
@ -341,6 +341,7 @@ import tw.nekomimi.nekogram.BackButtonMenuRecent;
|
|||
import tw.nekomimi.nekogram.NekoConfig;
|
||||
import tw.nekomimi.nekogram.SimpleTextViewSwitcher;
|
||||
import tw.nekomimi.nekogram.helpers.PopupHelper;
|
||||
import tw.nekomimi.nekogram.helpers.SponsorHelper;
|
||||
import tw.nekomimi.nekogram.helpers.remote.ConfigHelper;
|
||||
import tw.nekomimi.nekogram.settings.NekoSettingsActivity;
|
||||
import tw.nekomimi.nekogram.translator.Translator;
|
||||
|
|
@ -375,6 +376,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
private final Drawable[] verifiedCheckDrawable = new Drawable[2];
|
||||
private final CrossfadeDrawable[] verifiedCrossfadeDrawable = new CrossfadeDrawable[2];
|
||||
private final CrossfadeDrawable[] premiumCrossfadeDrawable = new CrossfadeDrawable[2];
|
||||
private final Drawable[] foxSponsorDrawable = new Drawable[2];
|
||||
private ScamDrawable scamDrawable;
|
||||
private UndoView undoView;
|
||||
private OverlaysView overlaysView;
|
||||
|
|
@ -2261,6 +2263,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
getNotificationCenter().addObserver(this, NotificationCenter.profileMusicUpdated);
|
||||
getNotificationCenter().addObserver(this, NotificationCenter.updatedChatRanks);
|
||||
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
|
||||
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.sponsorStatusUpdated);
|
||||
if (userId == getUserConfig().getClientUserId() || myProfile) {
|
||||
SponsorHelper.refresh(false);
|
||||
}
|
||||
updateRowsIds();
|
||||
if (listAdapter != null) {
|
||||
listAdapter.notifyDataSetChanged();
|
||||
|
|
@ -2402,6 +2408,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
getNotificationCenter().removeObserver(this, NotificationCenter.profileMusicUpdated);
|
||||
getNotificationCenter().removeObserver(this, NotificationCenter.updatedChatRanks);
|
||||
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
|
||||
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.sponsorStatusUpdated);
|
||||
if (avatarsViewPager != null) {
|
||||
avatarsViewPager.onDestroy();
|
||||
}
|
||||
|
|
@ -9185,6 +9192,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
public void didReceivedNotification(int id, int account, final Object... args) {
|
||||
if (id == NotificationCenter.uploadStoryEnd || id == NotificationCenter.chatWasBoostedByUser) {
|
||||
checkCanSendStoryForPosting();
|
||||
} else if (id == NotificationCenter.sponsorStatusUpdated) {
|
||||
if (userId != 0) {
|
||||
updateProfileData(false);
|
||||
}
|
||||
} else if (id == NotificationCenter.updateInterfaces) {
|
||||
int mask = (Integer) args[0];
|
||||
boolean infoChanged = (mask & MessagesController.UPDATE_MASK_AVATAR) != 0 || (mask & MessagesController.UPDATE_MASK_NAME) != 0 || (mask & MessagesController.UPDATE_MASK_STATUS) != 0 || (mask & MessagesController.UPDATE_MASK_EMOJI_STATUS) != 0;
|
||||
|
|
@ -11167,6 +11178,19 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
return verifiedCrossfadeDrawable[a];
|
||||
}
|
||||
|
||||
private Drawable getFoxSponsorDrawable(int a) {
|
||||
if (foxSponsorDrawable[a] == null) {
|
||||
Drawable d = ContextCompat.getDrawable(getParentActivity(), R.drawable.foxsponsor_badge).mutate();
|
||||
int color = getThemedColor(Theme.key_profile_verifiedBackground);
|
||||
if (a == 1) {
|
||||
color = dontApplyPeerColor(color);
|
||||
}
|
||||
d.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
foxSponsorDrawable[a] = d;
|
||||
}
|
||||
return foxSponsorDrawable[a];
|
||||
}
|
||||
|
||||
private Drawable getPremiumCrossfadeDrawable(int a) {
|
||||
if (premiumCrossfadeDrawable[a] == null) {
|
||||
premiumStarDrawable[a] = ContextCompat.getDrawable(getParentActivity(), R.drawable.msg_premium_liststar).mutate();
|
||||
|
|
@ -11538,6 +11562,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
} else if (getMessagesController().isDialogMuted(dialogId != 0 ? dialogId : userId, topicId)) {
|
||||
nameTextView[a].setRightDrawable2(getThemedDrawable(Theme.key_drawable_muteIconDrawable));
|
||||
nameTextViewRightDrawable2ContentDescription = LocaleController.getString(R.string.NotificationsMuted);
|
||||
} else if (user.self && SponsorHelper.isSponsor(user.id)) {
|
||||
nameTextView[a].setRightDrawable2(getFoxSponsorDrawable(a));
|
||||
nameTextViewRightDrawable2ContentDescription = LocaleController.getString(R.string.FoxSponsorBadge);
|
||||
} else {
|
||||
nameTextView[a].setRightDrawable2(null);
|
||||
nameTextViewRightDrawable2ContentDescription = null;
|
||||
|
|
@ -11561,6 +11588,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
|
|||
nameTextView[a].setRightDrawable2(getScamDrawable(user.scam ? 0 : 1));
|
||||
} else if (user.verified) {
|
||||
nameTextView[a].setRightDrawable2(getVerifiedCrossfadeDrawable(a));
|
||||
} else if (user.self && SponsorHelper.isSponsor(user.id)) {
|
||||
nameTextView[a].setRightDrawable2(getFoxSponsorDrawable(a));
|
||||
} else {
|
||||
nameTextView[a].setRightDrawable2(null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
package tw.nekomimi.nekogram.helpers;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Resolves the "sponsor" status of the current Telegram user against the
|
||||
* FoxCloud backend and caches it locally.
|
||||
*
|
||||
* Identification is done purely by Telegram ID: the backend endpoint
|
||||
* {@code GET /mobile/me} accepts an {@code X-Tg-Id} header and looks the user
|
||||
* up by the Telegram account that was linked on the website / bot. No
|
||||
* subscription URL or manual input is required.
|
||||
*
|
||||
* The result is cached per-account in shared preferences so the badge can be
|
||||
* drawn synchronously while a fresh check runs in the background. When the
|
||||
* cached value changes, {@link NotificationCenter#sponsorStatusUpdated} is
|
||||
* posted on the global instance.
|
||||
*/
|
||||
public final class SponsorHelper {
|
||||
|
||||
private SponsorHelper() {}
|
||||
|
||||
private static final String TAG = "SponsorHelper";
|
||||
private static final String BASE_URL = "https://vpnghost.space";
|
||||
private static final String PREFS = "foxsponsor";
|
||||
// Re-check at most once per hour while the value is fresh.
|
||||
private static final long TTL_MS = 60 * 60 * 1000L;
|
||||
|
||||
private static volatile boolean checking = false;
|
||||
|
||||
private static SharedPreferences prefs() {
|
||||
return ApplicationLoader.applicationContext.getSharedPreferences(PREFS, android.content.Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
/** Cached sponsor flag for the given Telegram user id. Defaults to false. */
|
||||
public static boolean isSponsor(long telegramId) {
|
||||
if (telegramId == 0) {
|
||||
return false;
|
||||
}
|
||||
return prefs().getBoolean("sponsor_" + telegramId, false);
|
||||
}
|
||||
|
||||
/** Convenience: sponsor flag for the currently selected account. */
|
||||
public static boolean isCurrentUserSponsor() {
|
||||
var user = UserConfig.getInstance(UserConfig.selectedAccount).getCurrentUser();
|
||||
return user != null && isSponsor(user.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick off a background refresh of the sponsor status for the current
|
||||
* account. Safe to call repeatedly: it self-throttles via {@link #TTL_MS}
|
||||
* unless {@code force} is set.
|
||||
*/
|
||||
public static void refresh(boolean force) {
|
||||
var user = UserConfig.getInstance(UserConfig.selectedAccount).getCurrentUser();
|
||||
if (user == null || user.id == 0) {
|
||||
return;
|
||||
}
|
||||
final long telegramId = user.id;
|
||||
if (checking) {
|
||||
return;
|
||||
}
|
||||
if (!force) {
|
||||
long last = prefs().getLong("checked_" + telegramId, 0);
|
||||
if (Math.abs(System.currentTimeMillis() - last) < TTL_MS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
checking = true;
|
||||
Utilities.globalQueue.postRunnable(() -> {
|
||||
try {
|
||||
doCheck(telegramId);
|
||||
} finally {
|
||||
checking = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// @WorkerThread
|
||||
private static void doCheck(long telegramId) {
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
URL url = new URL(BASE_URL + "/mobile/me");
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setInstanceFollowRedirects(true);
|
||||
connection.setConnectTimeout(15000);
|
||||
connection.setReadTimeout(15000);
|
||||
connection.setRequestProperty("X-Tg-Id", String.valueOf(telegramId));
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
|
||||
int code = connection.getResponseCode();
|
||||
if (code != HttpURLConnection.HTTP_OK) {
|
||||
FileLog.d(TAG + ": /mobile/me returned HTTP " + code);
|
||||
// Don't clobber a previously known value on transient errors.
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try (InputStream in = connection.getInputStream()) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int read;
|
||||
while ((read = in.read(buffer)) >= 0) {
|
||||
sb.append(new String(buffer, 0, read, "UTF-8"));
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject json = new JSONObject(sb.toString());
|
||||
if (!json.optBoolean("success", false)) {
|
||||
return;
|
||||
}
|
||||
boolean sponsor = json.optBoolean("is_sponsor", false);
|
||||
store(telegramId, sponsor);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void store(long telegramId, boolean sponsor) {
|
||||
boolean previous = prefs().getBoolean("sponsor_" + telegramId, false);
|
||||
prefs().edit()
|
||||
.putBoolean("sponsor_" + telegramId, sponsor)
|
||||
.putLong("checked_" + telegramId, System.currentTimeMillis())
|
||||
.apply();
|
||||
if (previous != sponsor) {
|
||||
AndroidUtilities.runOnUIThread(() ->
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.sponsorStatusUpdated));
|
||||
}
|
||||
}
|
||||
}
|
||||
9
TMessagesProj/src/main/res/drawable/foxsponsor_badge.xml
Normal file
9
TMessagesProj/src/main/res/drawable/foxsponsor_badge.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M12,2L14.6,7.27L20.42,8.12L16.21,12.22L17.2,18.02L12,15.28L6.8,18.02L7.79,12.22L3.58,8.12L9.4,7.27L12,2Z" />
|
||||
</vector>
|
||||
|
|
@ -149,6 +149,7 @@
|
|||
<string name="ShareNekogram">Share FoxiGram...</string>
|
||||
<string name="NekogramVersion">FoxiGram %1$s\nBased on Telegram %2$s\nDesigned by %3$s</string>
|
||||
<string name="UpdateInstalling">Installing update...</string>
|
||||
<string name="FoxSponsorBadge">Sponsor</string>
|
||||
<string name="UpdateDownloading">Downloading update...</string>
|
||||
<string name="UpdateInstallingNotification">A notification will be shown when the update completes.</string>
|
||||
<string name="UpdateInstallingRelaunch">The app will relaunch when the update completes.</string>
|
||||
|
|
|
|||
Loading…
Reference in a new issue