Skip to content

feat: rewarded ads thing so free user can also enjoy ad free#1918

Open
bajrangCoder wants to merge 5 commits intoAcode-Foundation:mainfrom
bajrangCoder:feat/rewarded-ads-for-free
Open

feat: rewarded ads thing so free user can also enjoy ad free#1918
bajrangCoder wants to merge 5 commits intoAcode-Foundation:mainfrom
bajrangCoder:feat/rewarded-ads-for-free

Conversation

@bajrangCoder
Copy link
Member

@bajrangCoder bajrangCoder commented Mar 1, 2026

  • Removes the ad from opening any folder to sidebar
  • Added a page where user can watch ads and enjoy uninterrupted ad free experience for certain time

@github-actions github-actions bot added the enhancement New feature or request label Mar 1, 2026
Copy link
Member

@RohitKushvaha01 RohitKushvaha01 left a comment

Choose a reason for hiding this comment

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

Authenticator.java is meant for login functionality. Why did you put the ad logic there? Put the logic in System.java or in a separate plugin.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 1, 2026

Greptile Summary

This PR implements a rewarded ads system allowing free users to watch ads in exchange for temporary ad-free time. Users can choose between two offers: Quick pass (1 ad = 1 hour) or Focus block (2 ads = 4-6 hours random). The system enforces daily limits (3 redemptions/day) and caps active ad-free time at 10 hours.

Key Changes:

  • Added complete reward management system with encrypted state storage via Android Authenticator plugin
  • Centralized ad display logic through helpers.canShowAds() and helpers.showInterstitialIfReady()
  • Removed intrusive folder-opening interstitial ad for better UX
  • New "Earn ad-free time" page accessible from settings

Issues Found:

  • Test ad unit ID for interstitial ads is incorrect (copy-pasted rewarded ID instead)
  • Missing timeout protection in rewarded ad promise - could hang indefinitely
  • Server-side verification setup exists but redemption happens client-side without verification gating (potential security gap)

Confidence Score: 3/5

  • This PR has solid architecture but contains one critical testing bug and one logical hang risk that should be fixed before merge
  • Score reflects well-structured implementation with good separation of concerns and encrypted state management, but reduced due to: (1) incorrect test ad unit ID that will break testing, (2) missing timeout that could cause app hangs, and (3) potential security gap in server-side verification flow. The core logic is sound and changes are well-integrated across the codebase.
  • Pay close attention to src/lib/startAd.js (test ID bug) and src/lib/adRewards.js (timeout + verification issues)

Important Files Changed

Filename Overview
src/lib/adRewards.js Core rewarded ads system with state management, offer definitions, and ad watching flow - lacks timeout protection in promise chain
src/plugins/auth/src/android/Authenticator.java Added reward state management with encrypted storage, daily limits (3/day), max active time (10h), and redemption validation - solid server-side logic
src/pages/adRewards/index.js Clean UI page for reward offers with real-time state updates and error handling
src/lib/startAd.js Added rewarded ad unit ID configuration - test ad unit ID for interstitial is incorrect (using rewarded ID)
src/utils/helpers.js Centralized ad display logic with reward state integration via canShowAds() and showInterstitialIfReady() helpers

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as Ad Rewards Page
    participant AR as adRewards.js
    participant AdMob as AdMob SDK
    participant Native as Authenticator.java
    participant Storage as Encrypted Prefs
    
    User->>UI: Click "Watch ad" button
    UI->>AR: watchOffer(offerId)
    AR->>Native: getStatus()
    Native->>Storage: Load reward state
    Storage-->>Native: Current state
    Native-->>AR: Validate limits
    
    alt Daily limit reached or 10h max exceeded
        AR-->>UI: Show error message
    else Can redeem
        loop For each ad in offer (1 or 2)
            AR->>AdMob: createRewardedAd()
            AR->>AdMob: load()
            AR->>AdMob: show()
            AdMob-->>User: Display ad
            User->>AdMob: Watch & complete ad
            AdMob-->>AR: Fire "reward" event
            AdMob->>Google: Server-side verification (async)
        end
        
        AR->>Native: redeem(offerId)
        Native->>Native: Check limits & calculate duration
        Native->>Storage: Save updated state
        Storage-->>Native: Success
        Native-->>AR: New state with expiry time
        AR->>AR: Hide active banner ads
        AR->>AR: Schedule expiry check
        AR-->>UI: Show success notification
        UI-->>User: "X hours unlocked" message
    end
Loading

Last reviewed commit: cede731

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

15 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +195 to +216
async function createRewardedAd(offer, step, sessionId) {
const rewardedUnitId = getRewardedUnitId();
if (!rewardedUnitId || !admob?.RewardedAd) {
throw new Error("Rewarded ads are not available in this build.");
}

const userId = await getRewardIdentity();
const customData = [
`session=${sessionId}`,
`offer=${offer.id}`,
`step=${step}`,
`ads=${offer.adsRequired}`,
].join("&");

return new admob.RewardedAd({
adUnitId: rewardedUnitId,
serverSideVerification: {
userId,
customData,
},
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

sets up server-side verification with custom data, but the client-side redeem() call (line 386) executes immediately after the client-side "reward" event fires, without waiting for server-side verification from Google.

This creates a potential race condition where rewards could be redeemed before Google's servers verify the ad was legitimately watched. A malicious modified app could trigger the reward event without actually displaying ads.

Consider implementing a backend webhook that receives Google's server-side verification callback and gates the secureAdRewardState.redeem() call on that verification.

@RohitKushvaha01

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants