Skip to content

Conversation

@jaasen-livefront
Copy link
Collaborator

@jaasen-livefront jaasen-livefront commented Nov 5, 2025

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-24722
https://bitwarden.atlassian.net/browse/PM-27695

📔 Objective

This PR does the following:

  • introduces a new callout at the top of the browser extension settings for non-premium users with a link to upgrade to premium
  • removes premium upgrade link from the "More from Bitwarden" page
  • adds missing specs for the settings-v2.compoent

📸 Screenshots

Screen.Recording.2025-11-06.at.1.08.33.PM.mov

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@github-actions
Copy link
Contributor

github-actions bot commented Nov 5, 2025

Logo
Checkmarx One – Scan Summary & Details292c2754-ad18-44ab-a8c2-2397d34bce58

New Issues (2)

Checkmarx found the following issues in this Pull Request

Severity Issue Source File / Package Checkmarx Insight
MEDIUM CVE-2025-62595 Npm-koa-2.16.1
detailsRecommended version: 2.16.3
Description: Koa is expressive middleware for Node.js using ES2017 async functions. A bypass to CVE-2025-8129 was discovered in the "Koa.js" framework, affectin...
Attack Vector: NETWORK
Attack Complexity: LOW

ID: EoO%2Fqyhpcjo1V0NpZPuVQWMeXvY8FM%2BdJGrqWkOrn38%3D
Vulnerable Package
MEDIUM CVE-2025-8129 Npm-koa-2.16.1
detailsRecommended version: 2.16.3
Description: A vulnerability, which was classified as problematic, was found in KoaJS Koa versions through 2.16.1 and versions 3.0.0-alpha0 through 3.0.0. Affec...
Attack Vector: NETWORK
Attack Complexity: LOW

ID: wHQXKcaCnpYjnt%2Bkw%2BjeO66bllnR%2FQ8RiSlkqZuC%2B8Y%3D
Vulnerable Package

@codecov
Copy link

codecov bot commented Nov 5, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 40.82%. Comparing base (4bf90b0) to head (9b554ec).
⚠️ Report is 65 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #17246      +/-   ##
==========================================
+ Coverage   40.51%   40.82%   +0.31%     
==========================================
  Files        3531     3542      +11     
  Lines      100931   101492     +561     
  Branches    15092    15219     +127     
==========================================
+ Hits        40897    41439     +542     
+ Misses      58314    58302      -12     
- Partials     1720     1751      +31     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@reneelund08
Copy link

This looks good to me!

@jaasen-livefront jaasen-livefront changed the title [PM-24722] - add persistent callout in settings for non-premium users [PM-24722][PM-27695] - add persistent callout in settings for non-premium users Nov 6, 2025
@jaasen-livefront jaasen-livefront marked this pull request as ready for review November 6, 2025 21:09
@jaasen-livefront jaasen-livefront requested review from a team as code owners November 6, 2025 21:09
@jaasen-livefront jaasen-livefront requested a review from a team as a code owner November 6, 2025 21:09
@theMickster
Copy link
Contributor

@claude: Review this PR

@bitwarden bitwarden deleted a comment from claude bot Nov 7, 2025
@bitwarden bitwarden deleted a comment from claude bot Nov 7, 2025
gbubemismith
gbubemismith previously approved these changes Nov 7, 2025
selector: "bit-spotlight",
templateUrl: "spotlight.component.html",
imports: [ButtonModule, CommonModule, IconButtonModule, I18nPipe, TypographyModule],
changeDetection: ChangeDetectionStrategy.OnPush,
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ did you notice any weirdness in the browser extension after making this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@gbubemismith Seems to be working as expected.

@gbubemismith
Copy link
Contributor

Looks like to have some conflicts

@gbubemismith gbubemismith self-requested a review November 7, 2025 16:55
@claude
Copy link

claude bot commented Nov 7, 2025

Claude encountered an error —— View job


I'll analyze this and get back to you.

Copy link
Contributor

Choose a reason for hiding this comment

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

What was the rationale for removing the separate premium component in favor of the inline spotlight callout?
Are there any other components or services that depend on or reference premium-v2.component?
Just want to make sure we're not missing any cleanup or migration steps for this component removal.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@cyprain-okeke Thanks for pointing this out. Looks like we have plans to remove this but it's still behind a feature flag. I've re-implemented the premium component for now.
b68cd34

cyprain-okeke
cyprain-okeke previously approved these changes Nov 13, 2025
Copy link
Contributor

@cyprain-okeke cyprain-okeke left a comment

Choose a reason for hiding this comment

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

Approved

Comment on lines 3 to 15
<span class="tw-text-xs"
>{{ "unlockFeaturesWithPremium" | i18n }}
<button
bitLink
buttonType="primary"
class="!tw-no-underline tw-text-xs !tw-font-semibold"
type="button"
(click)="openUpgradeDialog()"
[title]="'upgradeNow' | i18n"
>
{{ "upgradeNow" | i18n }}
</button></span
>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<span class="tw-text-xs"
>{{ "unlockFeaturesWithPremium" | i18n }}
<button
bitLink
buttonType="primary"
class="!tw-no-underline tw-text-xs !tw-font-semibold"
type="button"
(click)="openUpgradeDialog()"
[title]="'upgradeNow' | i18n"
>
{{ "upgradeNow" | i18n }}
</button></span
>
<span class="tw-text-xs">
{{ "unlockFeaturesWithPremium" | i18n }}
<button
bitLink
buttonType="primary"
class="!tw-no-underline tw-text-xs !tw-font-semibold"
type="button"
(click)="openUpgradeDialog()"
[title]="'upgradeNow' | i18n"
>
{{ "upgradeNow" | i18n }}
</button>
</span>

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed 8e02693

@Input() persistent = false;
readonly buttonText = input<string | null>(null);
// Whether the component can be dismissed, if true, the component will not show a close button
readonly persistent = input(false);
Copy link
Member

@Hinton Hinton Nov 13, 2025

Choose a reason for hiding this comment

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

suggestion: If you use input(false, { transform: booleanAttribute }); it works similar to the native disabled attribute, i.e. rather than having to do <bit-spotlight [persistent]="true" you can just write <bit-spotlight persistent.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@Hinton Ah yes ofc, thanks!. Fixed 8e02693

vleague2
vleague2 previously approved these changes Nov 18, 2025
Copy link
Contributor

@cyprain-okeke cyprain-okeke left a comment

Choose a reason for hiding this comment

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

No billing file was changes

gbubemismith
gbubemismith previously approved these changes Nov 19, 2025
Hinton
Hinton previously approved these changes Nov 20, 2025
Copy link
Member

@Hinton Hinton left a comment

Choose a reason for hiding this comment

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

Approved, but consider resolving the comments since they introduce tech debt.

// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
// eslint-disable-next-line @angular-eslint/prefer-signals
@Input({ required: true }) title: string | null = null;
readonly title = input<string | null>(null);
Copy link
Member

Choose a reason for hiding this comment

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

Just an FYI, but this title is now string | null | undefined. Do you actually use the null case, or could all of these be simplified to input<string> which is string | undefined.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah I think we can remove null for all these inputs. c861772

Copy link
Member

Choose a reason for hiding this comment

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

suggestion: We can clean up the canAccessPremium$ from the ts file, which also lets you cleanup billingAccountProfileStateService.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nice catch! Fixed c861772

return await this.autofillBrowserSettingsService.isBrowserAutofillSettingOverridden(
BrowserApi.getBrowserClientVendor(window),
);
}).pipe(shareReplay({ bufferSize: 1, refCount: true }));
Copy link
Member

Choose a reason for hiding this comment

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

question: What's up with defer and shareReplay({ bufferSize: 1, refCount: true })?

I don't think defer gains us anything here over from, and this observable should only be subscribed once in the template.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agreed this is probably overkill. Fixed c861772

await this.autofillBrowserSettingsService.isBrowserAutofillSettingOverridden(
BrowserApi.getBrowserClientVendor(window),
);
openUpgradeDialog() {
Copy link
Member

Choose a reason for hiding this comment

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

I would have preferred that this be protected, but I assume it's public for test reasons?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It does make testing simpler but we can easily just call component["openUpgradeDialog"]();. Fixed c861772

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.

8 participants