Skip to content

fix(notifications): add subscription removal#6211

Merged
shoom3301 merged 2 commits intodevelopfrom
fix/notifications-unsubscribe
Sep 3, 2025
Merged

fix(notifications): add subscription removal#6211
shoom3301 merged 2 commits intodevelopfrom
fix/notifications-unsubscribe

Conversation

@shoom3301
Copy link
Copy Markdown
Collaborator

@shoom3301 shoom3301 commented Sep 2, 2025

Summary

Needs this PR to be merged first: cowprotocol/cms#65

In this PR I added TG unsubscribe functionality.
Now you the toggle off the button and it will unsubscribe you.
Before you perform subscribe/unsubscribe you have to be authorized in Telegram.
We periodically check TG authorization and if there is no active session we display "Authorize Telegram" button.

To Test

Can be tested only on dev due to TG domain restrictions.

Summary by CodeRabbit

  • New Features

    • Authorize Telegram button when authorization is required.
    • One-click subscribe/unsubscribe toggle with clearer loading states.
    • Automatic authentication on connect for a smoother experience.
  • Refactor

    • More reliable session checks and subscription status handling to reduce connection friction.
  • Documentation

    • Updated Telegram subscription instructions to enable add, remove, and check permissions.

@shoom3301 shoom3301 requested a review from a team September 2, 2025 08:36
@shoom3301 shoom3301 self-assigned this Sep 2, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 2, 2025

Walkthrough

Introduces a new hook-based Telegram subscription flow: adds useTgSubscription, converts useTgAuthorization to promise-based authorize/authenticate, rewires ConnectTelegram to use these hooks (auto-authenticate on mount), updates TelegramConnectionStatus props/UI, and updates README Telegram permission instructions.

Changes

Cohort / File(s) Summary of Changes
Docs: Telegram permissions
apps/cowswap-frontend/src/modules/notifications/README.md
Update instructions to enable addSubscription, removeSubscription, and checkSubscription in Telegram subscription settings.
Authorization hook refactor
apps/cowswap-frontend/src/modules/notifications/hooks/useTgAuthorization.ts
Convert authorize() to return Promise<void>, add `authenticate(): Promise<TelegramData
New subscription hook
apps/cowswap-frontend/src/modules/notifications/hooks/useTgSubscription.ts
Add useTgSubscription(account, authorization) to manage isTgSubscribed, isCmsCallInProgress, implement toggleSubscription, and call CMS endpoints /add-tg-subscription, /remove-tg-subscription, /check-tg-subscription.
Container: Connect flow
apps/cowswap-frontend/src/modules/notifications/containers/ConnectTelegram.tsx
Replace inline CMS POST logic with useTgSubscription; use the authorization object (authorize, authenticate, tgData, isLoginInProgress, isAuthChecked); call authenticate() on mount; compute needsAuthorization; pass needsAuthorization, authorize, toggleSubscription to UI; update loading flags.
UI: Connection status
apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.tsx, .../index.cosmos.tsx
Change props: remove subscribeAccount, add needsAuthorization, authorize, toggleSubscription; render an Authorize button when needsAuthorization else render subscription Toggle; update fixtures to include needsAuthorization and authorize.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant CT as ConnectTelegram
  participant Auth as useTgAuthorization
  participant Sub as useTgSubscription
  participant TG as Telegram
  participant CMS as CMS API

  Note over CT: Component mount
  CT->>Auth: authenticate()
  Auth->>TG: getTelegramAuth
  TG-->>Auth: TelegramData|null
  Auth-->>CT: tgData / isAuthChecked

  alt tgData present
    CT->>Sub: init(account, Auth)
    Sub->>CMS: POST /check-tg-subscription
    CMS-->>Sub: { isSubscribed }
    Sub-->>CT: isTgSubscribed
  else needs authorization
    CT-->>U: show "Authorize Telegram"
    U->>CT: click Authorize
    CT->>Auth: authorize()
    Auth->>TG: login flow
    TG-->>Auth: success/denied
    Auth->>Auth: authenticate()
    Auth-->>CT: tgData ready
    CT->>Sub: POST /check-tg-subscription
    CMS-->>Sub: { isSubscribed }
  end

  U->>CT: toggle subscription
  CT->>Sub: toggleSubscription()
  alt adding
    Sub->>CMS: POST /add-tg-subscription
    CMS-->>Sub: { ok }
    Sub-->>CT: isTgSubscribed = true
  else removing
    Sub->>CMS: POST /remove-tg-subscription
    CMS-->>Sub: { ok }
    Sub-->>CT: isTgSubscribed = false
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

notifications

Suggested reviewers

  • alfetopito
  • elena-zh

Poem

A rabbit hops to call authenticate,
Taps authorize, then waits — elate.
CMS burrows check and toggle too,
Subscribed or not, the carrots grew.
Hooray — the hops make signals true. 🥕🐇

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/notifications-unsubscribe

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@shoom3301 shoom3301 requested a review from a team September 2, 2025 08:36
@vercel
Copy link
Copy Markdown

vercel Bot commented Sep 2, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
cowfi Ready Ready Preview Sep 2, 2025 8:58am
explorer-dev Ready Ready Preview Sep 2, 2025 8:58am
swap-dev Ready Ready Preview Sep 2, 2025 8:58am
widget-configurator Ready Ready Preview Sep 2, 2025 8:58am
2 Skipped Deployments
Project Deployment Preview Updated (UTC)
cosmos Ignored Ignored Sep 2, 2025 8:58am
sdk-tools Ignored Ignored Preview Sep 2, 2025 8:58am

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (7)
apps/cowswap-frontend/src/modules/notifications/hooks/useTgAuthorization.ts (2)

75-86: Session polling runs only when tgData exists — consider always polling with page-visibility guard.

This misses the “login in another tab” scenario when tgData is null. Polling unconditionally (but skipping when document.hidden) keeps state fresh without excess load.

-  useEffect(() => {
-    if (!tgData) return
-
-    const intervalId = setInterval(authenticate, TG_SESSION_CHECK_INTERVAL)
-
-    return () => {
-      clearInterval(intervalId)
-    }
-  }, [tgData, authenticate])
+  useEffect(() => {
+    const tick = () => {
+      if (typeof document !== 'undefined' && document.hidden) return
+      authenticate()
+    }
+    const intervalId = setInterval(tick, TG_SESSION_CHECK_INTERVAL)
+    return () => clearInterval(intervalId)
+  }, [authenticate])

9-11: Minor: handle NaN in REACT_APP_TG_BOT_ID parsing.

If REACT_APP_TG_BOT_ID is set but not numeric, parseInt yields NaN. Consider validating and falling back to the default ID.

Example:

const parsed = Number(process.env.REACT_APP_TG_BOT_ID)
const TG_BOT_ID = Number.isFinite(parsed) ? parsed : 7076584722
apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.tsx (2)

16-22: Expose an optional “isBusy” prop to disable interactions during in-flight CMS/TG calls.

Helps prevent double-submits/toggles and aligns with isCmsCallInProgress.

 interface TelegramConnectionStatusProps {
   isLoading: boolean
   isSubscribed: boolean
   needsAuthorization: boolean
   toggleSubscription(): void
   authorize(): Promise<void>
+  isBusy?: boolean
 }

24-30: Pass through new isBusy prop.

Keep signature in sync with the interface change.

 export function TelegramConnectionStatus({
   isLoading,
   isSubscribed,
   needsAuthorization,
   authorize,
   toggleSubscription,
+  isBusy,
 }: TelegramConnectionStatusProps): ReactNode {
apps/cowswap-frontend/src/modules/notifications/containers/ConnectTelegram.tsx (1)

44-51: Handle script load failures to avoid a stuck loader

Add an onerror handler so isTelegramScriptLoading doesn’t remain true on network/script errors.

   const scriptElement = document.createElement('script')
   scriptElement.src = TELEGRAM_AUTH_WIDGET_URL
   scriptElement.async = true
   scriptElement.onload = () => {
     setIsTelegramScriptLoading(false)
   }
+  scriptElement.onerror = () => {
+    setIsTelegramScriptLoading(false)
+  }
apps/cowswap-frontend/src/modules/notifications/hooks/useTgSubscription.ts (2)

22-35: Guard CMS calls and surface errors (optional)

  • Early-return from callSubscriptionApi is fine when account is falsy; consider an early-return in toggleSubscription too (UX clarity).
  • Consider adding .catch() with logging/toast for failures.

I can wire a lightweight error reporter (e.g., toast + console) around these calls if you want.


28-33: Idempotency note (optional)

If CMS endpoints aren’t idempotent, rapid toggles could cause flapping. Your in-flight guard reduces this; consider server-side idempotency by account+telegram user.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b04bfbf and 29e79d2.

📒 Files selected for processing (5)
  • apps/cowswap-frontend/src/modules/notifications/README.md (1 hunks)
  • apps/cowswap-frontend/src/modules/notifications/containers/ConnectTelegram.tsx (3 hunks)
  • apps/cowswap-frontend/src/modules/notifications/hooks/useTgAuthorization.ts (3 hunks)
  • apps/cowswap-frontend/src/modules/notifications/hooks/useTgSubscription.ts (1 hunks)
  • apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
apps/cowswap-frontend/src/modules/notifications/hooks/useTgSubscription.ts (2)
apps/cowswap-frontend/src/modules/notifications/hooks/useTgAuthorization.ts (1)
  • TgAuthorization (27-33)
libs/core/src/cms/utils/getCmsClient.ts (1)
  • getCmsClient (10-17)
apps/cowswap-frontend/src/modules/notifications/hooks/useTgAuthorization.ts (1)
apps/cowswap-frontend/src/modules/notifications/services/getTelegramAuth.ts (1)
  • getTelegramAuth (15-40)
apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.tsx (3)
libs/ui/src/pure/Button/index.tsx (1)
  • FancyButton (184-195)
libs/ui/src/pure/Loader/index.tsx (1)
  • Loader (32-43)
apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx (1)
  • Toggle (107-132)
apps/cowswap-frontend/src/modules/notifications/containers/ConnectTelegram.tsx (3)
apps/cowswap-frontend/src/modules/notifications/hooks/useTgAuthorization.ts (1)
  • useTgAuthorization (35-88)
apps/cowswap-frontend/src/modules/notifications/hooks/useTgSubscription.ts (1)
  • useTgSubscription (15-86)
apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.tsx (1)
  • TelegramConnectionStatus (24-44)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Setup
  • GitHub Check: Cypress
🔇 Additional comments (5)
apps/cowswap-frontend/src/modules/notifications/README.md (1)

10-10: Add “removeSubscription” permission — good catch.

This aligns the CMS role with the new unsubscribe flow.

Please confirm in the CMS (dev) that the three endpoints are actually exposed under:

  • POST /add-tg-subscription
  • POST /remove-tg-subscription
  • GET /check-tg-subscription

If the slugs differ, the hook calls will fail with 403/404.

apps/cowswap-frontend/src/modules/notifications/hooks/useTgAuthorization.ts (2)

40-50: authenticate() promise wrapper — LGTM.

Resolves on both success and failure paths from getTelegramAuth; state updates are consistent.


29-33: API change validated; no further action required

ConnectTelegram is the sole consumer—it invokes authenticate() on mount and passes authorize() into TelegramConnectionStatus, leveraging isAuthChecked and isLoginInProgress for loading state.

apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.tsx (1)

9-14: Styling looks consistent with FancyButton; good.

Padding and cursor improve UX.

apps/cowswap-frontend/src/modules/notifications/containers/ConnectTelegram.tsx (1)

68-74: Prop wiring looks correct

TelegramConnectionStatus receives the right flags and handlers, matching the new auth/subscription split.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.cosmos.tsx (3)

3-4: Align handler name with prop and add useful no-op logs

Keeps fixture intent clear and makes clicks visible in Cosmos.

-const subscribeAccount = (): void => {}
-const authorize = (): Promise<void> => Promise.resolve()
+const toggleSubscription = (): void => {
+  console.info('[cosmos] toggleSubscription clicked')
+}
+const authorize = async (): Promise<void> => {
+  console.info('[cosmos] authorize clicked')
+}

26-33: Rename fixture for clarity

“needLogin” is misleading now that authorization is explicit. Prefer “unsubscribed”.

Update key name (illustrative):

const Fixtures = {
  // ...
  unsubscribed: () => (
    <TelegramConnectionStatus
      isLoading={false}
      isSubscribed={false}
      needsAuthorization={false}
      authorize={authorize}
      toggleSubscription={toggleSubscription}
    />
  ),
}

Also, if you adopt the handler rename above, switch the prop value here to toggleSubscription.

-      toggleSubscription={subscribeAccount}
+      toggleSubscription={toggleSubscription}

34-41: LGTM: needsAuthorization fixture

Covers auth CTA path. If you rename the handler, adjust prop value accordingly.

-      toggleSubscription={subscribeAccount}
+      toggleSubscription={toggleSubscription}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 29e79d2 and c8977d6.

📒 Files selected for processing (1)
  • apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.cosmos.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.cosmos.tsx (1)
apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.tsx (1)
  • TelegramConnectionStatus (24-44)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Setup
  • GitHub Check: Cypress
🔇 Additional comments (2)
apps/cowswap-frontend/src/modules/notifications/pure/TelegramConnectionStatus/index.cosmos.tsx (2)

7-15: LGTM: loading state fixture

Props match component contract; loader path covered.


17-23: LGTM: subscribed state fixture

Covers active toggle path.

@shoom3301 shoom3301 merged commit d21a022 into develop Sep 3, 2025
15 checks passed
@shoom3301 shoom3301 deleted the fix/notifications-unsubscribe branch September 3, 2025 07:15
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 3, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants