-
Notifications
You must be signed in to change notification settings - Fork 47
feat: Add vshare version checking and notification badge #152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,3 +26,6 @@ fastlane/*.json | |
| vendor/bundle/ | ||
| .bundle/ | ||
| Gemfile.lockfastlane/node_modules/ | ||
|
|
||
| # Documentation | ||
| .doc/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| package me.ghui.v2er.network.bean; | ||
|
|
||
| import com.google.gson.annotations.SerializedName; | ||
|
|
||
| /** | ||
| * Vshare page version information | ||
| * Used to check if the vshare page content has been updated | ||
| */ | ||
| public class VshareVersionInfo extends BaseInfo { | ||
| @SerializedName("version") | ||
| private int version; | ||
|
|
||
| @SerializedName("lastUpdated") | ||
| private String lastUpdated; | ||
|
|
||
| public VshareVersionInfo() { | ||
| } | ||
|
|
||
| public int getVersion() { | ||
| return version; | ||
| } | ||
|
|
||
| public void setVersion(int version) { | ||
| this.version = version; | ||
| } | ||
|
|
||
| public String getLastUpdated() { | ||
| return lastUpdated; | ||
| } | ||
|
|
||
| public void setLastUpdated(String lastUpdated) { | ||
| this.lastUpdated = lastUpdated; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isValid() { | ||
| return version > 0; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,121 @@ | ||||||||||||||||||||||
| package me.ghui.v2er.util; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import android.content.Context; | ||||||||||||||||||||||
| import android.content.SharedPreferences; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import io.reactivex.Observable; | ||||||||||||||||||||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||||||||||||||||||||
| import io.reactivex.schedulers.Schedulers; | ||||||||||||||||||||||
| import me.ghui.v2er.network.APIService; | ||||||||||||||||||||||
| import me.ghui.v2er.network.bean.VshareVersionInfo; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /** | ||||||||||||||||||||||
| * Checks for vshare page version updates | ||||||||||||||||||||||
| * Queries the API every 24 hours to check if the vshare page has been updated | ||||||||||||||||||||||
| */ | ||||||||||||||||||||||
| public class VshareVersionChecker { | ||||||||||||||||||||||
| private static final String PREFS_NAME = "vshare_version"; | ||||||||||||||||||||||
| private static final String KEY_LAST_VERSION = "last_version"; | ||||||||||||||||||||||
| private static final String KEY_LAST_CHECK_TIME = "last_check_time"; | ||||||||||||||||||||||
| private static final long CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours in milliseconds | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| private final Context context; | ||||||||||||||||||||||
| private final SharedPreferences prefs; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| public VshareVersionChecker(Context context) { | ||||||||||||||||||||||
| this.context = context.getApplicationContext(); | ||||||||||||||||||||||
| this.prefs = this.context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /** | ||||||||||||||||||||||
| * Checks if there's a new version available | ||||||||||||||||||||||
| * Only performs network request if 24 hours have passed since last check | ||||||||||||||||||||||
| * | ||||||||||||||||||||||
| * @return Observable<Boolean> - true if there's an update, false otherwise | ||||||||||||||||||||||
| */ | ||||||||||||||||||||||
| public Observable<Boolean> checkForUpdate() { | ||||||||||||||||||||||
| long lastCheckTime = prefs.getLong(KEY_LAST_CHECK_TIME, 0); | ||||||||||||||||||||||
| long currentTime = System.currentTimeMillis(); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // If less than 24 hours since last check, return cached result | ||||||||||||||||||||||
| if (currentTime - lastCheckTime < CHECK_INTERVAL) { | ||||||||||||||||||||||
| return Observable.just(hasUpdate()); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Perform network request | ||||||||||||||||||||||
| return APIService.get() | ||||||||||||||||||||||
| .getVshareVersion() | ||||||||||||||||||||||
| .subscribeOn(Schedulers.io()) | ||||||||||||||||||||||
| .observeOn(AndroidSchedulers.mainThread()) | ||||||||||||||||||||||
| .map(versionInfo -> { | ||||||||||||||||||||||
| if (versionInfo != null && versionInfo.isValid()) { | ||||||||||||||||||||||
| int serverVersion = versionInfo.getVersion(); | ||||||||||||||||||||||
| int localVersion = prefs.getInt(KEY_LAST_VERSION, 0); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // Update last check time | ||||||||||||||||||||||
| prefs.edit() | ||||||||||||||||||||||
| .putLong(KEY_LAST_CHECK_TIME, currentTime) | ||||||||||||||||||||||
| .apply(); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // If server version is newer, return true | ||||||||||||||||||||||
| return serverVersion > localVersion; | ||||||||||||||||||||||
|
Comment on lines
+60
to
+61
|
||||||||||||||||||||||
| // If server version is newer, return true | |
| return serverVersion > localVersion; | |
| // If server version is newer, persist it and return true | |
| if (serverVersion > localVersion) { | |
| prefs.edit() | |
| .putInt(KEY_LAST_VERSION, serverVersion) | |
| .apply(); | |
| return true; | |
| } | |
| return false; |
Copilot
AI
Oct 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] markAsViewed() performs an extra network request solely to record a version the app already had when showing the badge. Cache the server version during checkForUpdate() and write it directly here (or pass it in) to avoid an unnecessary call.
Copilot
AI
Oct 16, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hasUpdate() always returns false, making the cached path (within 24h) ineffective and wiping any pending badge state. Either cache the last known server version separately and compare it to a stored viewed version, or persist a boolean flag indicating an unseen update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Multiple hard-coded dp values and negative insets are brittle; consider computing offsets based on intrinsic sizes (icon + badge) or centralizing these values as named constants to ease future adjustments and ensure compatibility across densities and API levels.