Skip to content

Conversation

@graycreate
Copy link
Member

Summary

This PR implements a vshare version checking system with notification badges to inform users when new content is available on the vshare page.

Features Implemented

  • ✅ VshareVersionInfo model for parsing API response
  • ✅ VshareVersionChecker with 24-hour caching logic
  • ✅ "发现更多" navigation menu item
  • ✅ Red dot badge on navigation menu item
  • ✅ Red dot badge on hamburger menu icon (using LayerDrawable)
  • ✅ Automatic badge clearing when user views page

Technical Details

  • Uses RxJava for async API calls
  • SharedPreferences for local version storage
  • LayerDrawable approach for hamburger icon badge
  • 24-hour check interval to reduce API calls

Visual Changes

  • Red notification dot appears on both:
    • Navigation drawer "发现更多" menu item
    • Hamburger menu icon in the top-left corner

Testing

  • Tested version checking functionality
  • Verified badge appears when server version > local version
  • Confirmed badges clear after user clicks menu item
  • Badge positioning validated on hamburger icon

🤖 Generated with Claude Code

graycreate and others added 3 commits October 16, 2025 23:53
- Add VshareVersionInfo model for parsing API response
- Add VshareVersionChecker with 24-hour caching logic
- Add "发现更多" menu item in navigation drawer
- Extend BaseToolBar to support navigation icon badges
- Show red dot badge on both navigation menu and hamburger icon when updates available
- Badge clears when user clicks menu item and views page

This feature notifies users when new content is available on the vshare page by displaying a red notification dot on both the navigation menu item and the hamburger menu button.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Remove BaseToolBar extension approach that wasn't working properly
- Implement LayerDrawable approach to overlay badge on navigation icon
- Create navigation icon with embedded red dot badge
- Switch between original icon and badged icon based on update status

The badge now correctly appears on the hamburger menu icon in the top-left corner.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copilot AI review requested due to automatic review settings October 16, 2025 16:07
@graycreate graycreate merged commit 4596aa7 into main Oct 16, 2025
4 checks passed
@graycreate graycreate deleted the feature/vshare-version-check branch October 16, 2025 16:08
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds a vshare version check feature with UI notification badges (red dots) on the navigation drawer item and the toolbar hamburger icon to alert users of new vshare content. Key additions include a version info model, a version checker with 24‑hour caching logic, UI resources (icon, badge layout, shape), and integration into MainActivity and toolbar.

  • Adds VshareVersionInfo model and VshareVersionChecker utility
  • Adds navigation menu item with badge layout and toolbar badge logic
  • Integrates version checking and badge visibility updates in MainActivity

Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
app/src/main/res/values/strings.xml Adds localized string for the new vshare menu item.
app/src/main/res/menu/navigation_menu.xml Adds vshare navigation item with custom action layout for badge.
app/src/main/res/layout/layout_vshare_badge.xml Defines badge (red dot) layout container.
app/src/main/res/drawable/vshare_nav_item.xml Adds vector icon for vshare menu entry.
app/src/main/res/drawable/shape_badge_dot.xml Adds red dot shape drawable used for badges.
app/src/main/java/me/ghui/v2er/widget/BaseToolBar.java Adds navigation badge support (creation/show/hide logic).
app/src/main/java/me/ghui/v2er/util/VshareVersionChecker.java Implements version checking, caching, and view acknowledgment logic.
app/src/main/java/me/ghui/v2er/network/bean/VshareVersionInfo.java Data model for version response with validation.
app/src/main/java/me/ghui/v2er/network/APIs.java Adds API endpoint for vshare version JSON.
app/src/main/java/me/ghui/v2er/module/home/MainActivity.java Integrates version checker, badge handling for menu and toolbar, and navigation handling.

Comment on lines +60 to +61
// If server version is newer, return true
return serverVersion > localVersion;
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server version is never persisted here when a newer version is detected, so subsequent checks within 24h fall back to hasUpdate() which always returns false, causing the badge to disappear incorrectly before the user views the content. Persist the serverVersion (e.g. putInt(KEY_LAST_VERSION, serverVersion)) or store a separate 'latest_server_version' and compare it to a 'viewed_version'.

Suggested change
// 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 uses AI. Check for mistakes.
Comment on lines +97 to +106
private boolean hasUpdate() {
int lastVersion = prefs.getInt(KEY_LAST_VERSION, 0);
// If we haven't checked yet, assume no update
if (lastVersion == 0) {
return false;
}
// This would need server version to compare, but we're using cached data
// In practice, this will be updated by checkForUpdate()
return false;
}
Copy link

Copilot AI Oct 16, 2025

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.

Copilot uses AI. Check for mistakes.
Comment on lines +75 to +88
public void markAsViewed() {
APIService.get()
.getVshareVersion()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(versionInfo -> {
if (versionInfo != null && versionInfo.isValid()) {
prefs.edit()
.putInt(KEY_LAST_VERSION, versionInfo.getVersion())
.apply();
}
}, throwable -> {
// Silently ignore errors
});
Copy link

Copilot AI Oct 16, 2025

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 uses AI. Check for mistakes.
Comment on lines +86 to +94
public void showNavigationBadge() {
// Initialize badge if needed
if (mNavigationBadge == null) {
initNavigationBadge();
}

if (mNavigationBadge != null) {
mNavigationBadge.setVisibility(VISIBLE);
}
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If mNavigationBadge is null, initNavigationBadge() posts a creation runnable; the badge is created later with GONE visibility and never updated to VISIBLE because this method returns before creation completes. Move the visibility change into the post() block in initNavigationBadge() (conditional flag) or provide a callback so the badge becomes visible after asynchronous creation.

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +72
badgeParams.leftMargin = ScaleUtils.dp(36); // 16dp padding + 24dp icon - 4dp overlap
badgeParams.topMargin = ScaleUtils.dp(12); // Position at top of icon
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Magic numbers (36, 12) with inline arithmetic commentary reduce clarity and adaptability (e.g., RTL, different toolbar sizes). Extract these to named constants or derive from actual view dimensions at runtime.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +6
android:paddingEnd="16dp"
android:paddingRight="16dp">
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Redundant simultaneous use of paddingEnd and paddingRight; prefer only paddingEnd (and possibly paddingStart) for proper RTL support unless an explicit legacy fallback is required.

Suggested change
android:paddingEnd="16dp"
android:paddingRight="16dp">
android:paddingEnd="16dp">

Copilot uses AI. Check for mistakes.
android:layout_height="8dp"
android:layout_gravity="center_vertical"
android:background="@drawable/shape_badge_dot"
android:visibility="gone" />
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decorative badge view lacks accessibility suppression; add android:importantForAccessibility="no" (or focusable="false" and contentDescription="") so screen readers do not announce an unlabeled visual element.

Suggested change
android:visibility="gone" />
android:visibility="gone"
android:importantForAccessibility="no" />

Copilot uses AI. Check for mistakes.
android:viewportHeight="24">
<!-- Share/Discovery icon representing multiple apps/products -->
<path
android:fillColor="#757575"
Copy link

Copilot AI Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Hard-coded fillColor may not adapt to light/dark themes or dynamic color; reference a theme attribute or color resource (e.g., ?attr/icon_tint_color) and rely on tinting for consistency.

Suggested change
android:fillColor="#757575"
android:fillColor="?attr/colorControlNormal"

Copilot uses AI. Check for mistakes.
Comment on lines +170 to +175
// Position the badge at the top-right corner of the icon
// Navigation icon is 24dp, badge is 8dp
mNavIconWithBadge.setLayerSize(1, ScaleUtils.dp(8), ScaleUtils.dp(8));
mNavIconWithBadge.setLayerGravity(1, Gravity.TOP | Gravity.END);
mNavIconWithBadge.setLayerInsetEnd(1, -ScaleUtils.dp(4)); // Overlap with icon edge
mNavIconWithBadge.setLayerInsetTop(1, -ScaleUtils.dp(4)); // Overlap with icon edge
Copy link

Copilot AI Oct 16, 2025

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants