Skip to content

feat(account): add session management as standalone Sessions page#8961

Open
wangsijie wants to merge 10 commits into
masterfrom
devin/sessions-locale-translations
Open

feat(account): add session management as standalone Sessions page#8961
wangsijie wants to merge 10 commits into
masterfrom
devin/sessions-locale-translations

Conversation

@wangsijie
Copy link
Copy Markdown
Contributor

@wangsijie wangsijie commented Jun 5, 2026

Summary

Add standalone Sessions page (/sessions) to account center with two sections: Sessions and Third-party grants, aligned with Console's User Management UI patterns.

  • Standalone page at /sessions (parallel to /security, /profile), gated by accountCenter.fields.session (Off/ReadOnly/Edit)
  • Sessions section: lists active sessions with device info (UA parsed via ua-parser-js + safeParse()), location, IP, sign-in timestamp, "Current session" badge. Edit mode shows "Sign out" for non-current sessions
  • Third-party grants section: groups grants by applicationId, shows authorized date, "Remove" button in Edit mode. Only renders when grants fetch succeeds
  • Verification flow via VerifiedAction with 'load-sessions' pending action
  • hasVisibleSessionsPage() extracted so session field no longer gates Security page visibility
  • All locale translations provided for 18 languages

Testing

Tested locally

Link to Devin session: https://app.devin.ai/sessions/d135c0c480f6408da2d84b708b66b472
Requested by: @wangsijie

wangsijie and others added 7 commits June 3, 2026 13:44
Add SessionSection component to the account center Security page,
allowing users to view active sessions and revoke non-current ones.

Changes:
- Add UserScope.Sessions to OIDC scopes in App.tsx
- Create apis/sessions.ts with getSessions and revokeSession
- Create SessionSection component with session list, current session
  badge, revoke confirmation modal, and identity verification flow
- Add session field check to hasVisibleSecuritySection
- Add 'load-sessions' to pending verified actions
- Add i18n phrases for session management across all locales
…ement

- Replace custom UA parser with ua-parser-js (consistent with Console)
- Use userSessionSignInContextGuard.safeParse for safe context parsing
- Adopt grid-based row layout matching SocialSection pattern
- Show device name, location, IP, and sign-in time per session
- Use danger-colored revoke button (consistent with Console conventions)
- Add responsive mobile layout with mixin pattern
- Extract SessionSection from Security page into standalone /sessions route
- Split into two sections: Sessions and Third-party grants (aligned with Console user management)
- Add grants API (getGrants, revokeGrant)
- Add navigation support (sidebar, mobile tab)
- Fix PR comments: hasLoaded on error, double-parse UA, timestamp handling
- Add i18n keys with UNTRANSLATED markers for non-English locales
Copilot AI review requested due to automatic review settings June 5, 2026 06:41
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

COMPARE TO master

Total Size Diff ⚠️ 📈 +46.7 KB

Diff by File
Name Diff
packages/account/src/App.tsx 📈 +445 Bytes
packages/account/src/apis/sessions.ts 📈 +1.57 KB
packages/account/src/assets/icons/sessions.svg 📈 +470 Bytes
packages/account/src/components/MobileTabNav/index.test.tsx 📈 +63 Bytes
packages/account/src/components/account-nav-items.test.ts 📈 +147 Bytes
packages/account/src/components/account-nav-items.ts 📈 +366 Bytes
packages/account/src/constants/routes.ts 📈 +42 Bytes
packages/account/src/jest.setup.ts 📈 +95 Bytes
packages/account/src/pages/Security/index.test.tsx 📈 +52 Bytes
packages/account/src/pages/Sessions/GrantRow.tsx 📈 +1.27 KB
packages/account/src/pages/Sessions/SessionRow.tsx 📈 +1.79 KB
packages/account/src/pages/Sessions/index.module.scss 📈 +2.84 KB
packages/account/src/pages/Sessions/index.tsx ⚠️ 📈 +11.01 KB
packages/account/src/pages/Sessions/utils.ts 📈 +3.49 KB
packages/account/src/pages/VerifiedAction/index.tsx 📈 +303 Bytes
packages/account/src/utils/security-page.ts 📈 +314 Bytes
packages/account/src/utils/session-storage.ts 📈 +19 Bytes
packages/phrases-experience/src/locales/ar/account-center.ts 📈 +1.41 KB
packages/phrases-experience/src/locales/cs/account-center.ts 📈 +1.07 KB
packages/phrases-experience/src/locales/de/account-center.ts 📈 +1.12 KB
packages/phrases-experience/src/locales/en/account-center.ts 📈 +1023 Bytes
packages/phrases-experience/src/locales/es/account-center.ts 📈 +1.08 KB
packages/phrases-experience/src/locales/fr/account-center.ts 📈 +1.08 KB
packages/phrases-experience/src/locales/it/account-center.ts 📈 +1.08 KB
packages/phrases-experience/src/locales/ja/account-center.ts 📈 +1.34 KB
packages/phrases-experience/src/locales/ko/account-center.ts 📈 +1.09 KB
packages/phrases-experience/src/locales/pl-pl/account-center.ts 📈 +1.08 KB
packages/phrases-experience/src/locales/pt-br/account-center.ts 📈 +1.03 KB
packages/phrases-experience/src/locales/pt-pt/account-center.ts 📈 +1.08 KB
packages/phrases-experience/src/locales/ru/account-center.ts 📈 +1.49 KB
packages/phrases-experience/src/locales/th/account-center.ts 📈 +2.06 KB
packages/phrases-experience/src/locales/tr-tr/account-center.ts 📈 +1.12 KB
packages/phrases-experience/src/locales/uk-ua/account-center.ts 📈 +1.44 KB
packages/phrases-experience/src/locales/zh-cn/account-center.ts 📈 +949 Bytes
packages/phrases-experience/src/locales/zh-hk/account-center.ts 📈 +1 KB
packages/phrases-experience/src/locales/zh-tw/account-center.ts 📈 +1 KB

Copy link
Copy Markdown
Contributor

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 new standalone Sessions page to the Account Center (/sessions) to let end users view/revoke active sessions and manage third‑party application grants, while integrating with the existing verification flow and navigation gating via Account Center settings.

Changes:

  • Introduces a new /sessions route + sidebar/nav item gated by accountCenter.fields.session.
  • Implements Sessions UI (sessions list + third‑party grants list) with revoke actions and verification pending action (load-sessions).
  • Adds full i18n coverage for Sessions strings across the provided locales.

Reviewed changes

Copilot reviewed 34 out of 35 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/phrases-experience/src/locales/ar/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Arabic).
packages/phrases-experience/src/locales/cs/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Czech).
packages/phrases-experience/src/locales/de/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (German).
packages/phrases-experience/src/locales/en/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (English).
packages/phrases-experience/src/locales/es/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Spanish).
packages/phrases-experience/src/locales/fr/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (French).
packages/phrases-experience/src/locales/it/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Italian).
packages/phrases-experience/src/locales/ja/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Japanese).
packages/phrases-experience/src/locales/ko/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Korean).
packages/phrases-experience/src/locales/pl-pl/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Polish).
packages/phrases-experience/src/locales/pt-br/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Portuguese BR).
packages/phrases-experience/src/locales/pt-pt/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Portuguese PT).
packages/phrases-experience/src/locales/ru/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Russian).
packages/phrases-experience/src/locales/th/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Thai).
packages/phrases-experience/src/locales/tr-tr/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Turkish).
packages/phrases-experience/src/locales/uk-ua/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Ukrainian).
packages/phrases-experience/src/locales/zh-cn/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Simplified Chinese).
packages/phrases-experience/src/locales/zh-hk/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Traditional Chinese, HK).
packages/phrases-experience/src/locales/zh-tw/account-center.ts Adds Sessions sidebar label + Sessions/grants strings (Traditional Chinese, TW).
packages/account/src/utils/session-storage.ts Adds load-sessions to the pending verified action union.
packages/account/src/utils/security-page.ts Adds hasVisibleSessionsPage() gating for route/nav visibility.
packages/account/src/pages/VerifiedAction/index.tsx Allows the verification flow when pending action is load-sessions.
packages/account/src/pages/Sessions/utils.ts Adds UA parsing + timestamp formatting + grant grouping utilities.
packages/account/src/pages/Sessions/SessionRow.tsx Renders a session row, including “Current session” badge and revoke button.
packages/account/src/pages/Sessions/GrantRow.tsx Renders a third‑party app grant group row with revoke action.
packages/account/src/pages/Sessions/index.tsx Implements the Sessions page data loading, verification integration, and revoke flows.
packages/account/src/pages/Sessions/index.module.scss Styles for Sessions page rows/cards and mobile layout.
packages/account/src/pages/Security/index.test.tsx Updates Security test setup to include session field.
packages/account/src/constants/routes.ts Adds sessionsRoute constant.
packages/account/src/components/MobileTabNav/index.test.tsx Updates nav item builder usage to include hasSessions.
packages/account/src/components/account-nav-items.ts Adds Sessions nav item and icon wiring.
packages/account/src/components/account-nav-items.test.ts Updates/expands tests for sessions nav item.
packages/account/src/assets/icons/sessions.svg Adds Sessions icon SVG.
packages/account/src/App.tsx Registers /sessions route, nav visibility, full-page layout logic, and Sessions scope.
packages/account/src/apis/sessions.ts Adds Account Center APIs for sessions/grants list + revocation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/account/src/pages/Sessions/utils.ts Outdated
Comment thread packages/account/src/pages/Sessions/index.tsx
Comment thread packages/account/src/pages/Sessions/index.tsx
Comment thread packages/account/src/pages/Sessions/index.tsx
Comment thread packages/account/src/pages/Sessions/index.tsx Outdated
@devin-ai-integration
Copy link
Copy Markdown
Contributor

Test Report: Standalone Sessions Page

All 4 tests passed. Tested locally with the refactored Sessions page.

Test Results
# Test Result
1 Sessions page navigation & structure (Edit mode) ✅ Passed
2 Verification flow → session list loads ✅ Passed
3 Field visibility Off → page hidden ✅ Passed
4 Security page no longer has SessionSection ✅ Passed

Screenshots

Sessions Page (Pre-verification)

Standalone page at /account/sessions with sidebar nav, "Manage" button visible.

Sessions page pre-verification

Sessions Page (Post-verification)

After password verification, sessions list and Third-party apps section load correctly.

Sessions page post-verification

Field Off → Page Hidden

Setting session: "Off" hides the Sessions nav link and returns home for /account/sessions.

Sessions page hidden

Security Page (No SessionSection)

Security page only shows Password section — SessionSection fully removed.

Security page without sessions

Final Sessions Page View

Complete view with both sections: Sessions (current session with metadata) and Third-party apps (empty state).

Final sessions page

Not Fully Tested in Dev

  • Revoke session flow: Requires multiple concurrent sessions
  • Third-party grants removal: Requires a third-party app with active grants
  • ReadOnly mode: Similar to Edit but without action buttons

…atures

- Sort grant rows by numeric iat instead of locale-formatted string
- Only remove grant row from UI when all revocations succeed
- Handle grant fetch errors via handleError
- Gate grants section on grantRows !== undefined
- Gate Sessions page behind isDevFeaturesEnabled
return (
<div className={classNames(styles.row, layoutClassNames.row)}>
<div className={styles.sessionInfo}>
<div className={styles.deviceName}>{app.applicationId}</div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This renders app.applicationId (the raw OIDC clientId, an opaque ID) as the app name. The Console solves the same screen with <ApplicationName applicationId={…} /> (packages/console/.../UserSessionDetails), which resolves the human-readable name and handles deleted/system-app fallbacks. As-is, end users see authorized apps as bare client IDs and can't tell what they're revoking. Since this is end-user-facing, worth resolving the app name (likely needs a my-account-scoped applications lookup or an ApplicationName equivalent).

Copy link
Copy Markdown
Contributor

@simeng-li simeng-li Jun 8, 2026

Choose a reason for hiding this comment

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

Follow-up: rather than resolving the name on the client (extra fetch + an ApplicationName-style component), it may be cleaner to extend the response body of the account grants endpoint (GET /api/my-account/sessions) to include the application name alongside clientId — the backend already has the application record at hand when assembling grants, so it can join the name server-side. That keeps GrantRow a dumb renderer and avoids an N+1 lookup per app on the client.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed — extending the backend response is the cleaner approach. Will address as a follow-up since it requires a schema/API change.

Comment on lines +87 to +115
useEffect(() => {
if (!verificationId) {
return;
}

const pendingAction = sessionStorage.getPendingVerifiedAction();

if (pendingAction !== 'load-sessions') {
return;
}

sessionStorage.clearPendingVerifiedAction();
void fetchData(verificationId);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [verificationId]);

useEffect(() => {
if (hasLoaded || isLoading || !verificationId) {
return;
}

const pendingAction = sessionStorage.getPendingVerifiedAction();
if (pendingAction === 'load-sessions') {
return;
}

void fetchData(verificationId);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [verificationId, hasLoaded, isLoading]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Double-fetch race between these two effects on the verified-return path. When returning with pendingAction === 'load-sessions', both effects run on the same commit: effect 1 calls clearPendingVerifiedAction() then fetchData(), but its setIsLoading(true) isn't visible to effect 2's stale isLoading=false closure. Because effect 1 already cleared the sessionStorage flag, effect 2's pendingAction === 'load-sessions' guard no longer bails and it calls fetchData() a second time → two concurrent GET /sessions + GET /grants pairs (and a doubled error handler on permission_denied). Consider collapsing to a single load effect keyed off (verificationId, pendingAction).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed — collapsed to a single useEffect keyed on verificationId. Added an isFetchingRef guard to prevent concurrent fetches. The effect clears pendingAction if present and calls fetchData in one path.

Comment on lines +51 to +68
const [sessionError, sessionResult] = await getSessionsApi(verifiedId);

if (sessionError) {
await handleError(sessionError, {
'verification_record.permission_denied': async () => {
setVerificationId(undefined);
setToast(t('account_center.verification.verification_required'));
},
});
setIsLoading(false);
return;
}

if (sessionResult) {
setSessions(sessionResult.sessions);
}

const [grantError, grantResult] = await getGrantsApi(verifiedId);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sessions and grants are fetched strictly sequentially, but the two requests are independent. Running them with Promise.all (then applying error handling per-result) would roughly halve time-to-content.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed — sessions and grants now fetch in parallel with Promise.all.

</div>
</div>

{hasLoaded && grantRows !== undefined && (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When getGrants fails with a non-permission_denied error (500/timeout), grantRows stays undefined, so this whole section is hidden via grantRows !== undefined. A toast fires, but the section's absence is indistinguishable from "no apps" — the user can't tell grant loading failed. Consider an explicit error/empty state instead of hiding.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed — the grants section now always renders when hasLoaded is true. If grantRows is undefined (fetch failed), it falls through to the "no third-party apps" empty state. The toast from handleError already fires to indicate the failure.

Comment on lines +24 to +37
const getParsedUserAgentInfo = (userAgent?: string): ParsedUserAgentInfo => {
if (!userAgent) {
return {};
}

const { device, browser, os } = new UAParser(userAgent).getResult();
const deviceModel = [device.vendor, device.model].filter(Boolean).join(' ') || undefined;

return {
browserName: browser.name,
osName: os.name,
deviceModel,
};
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

getParsedUserAgentInfo, formatSessionDeviceName, formatSessionLocation, getSessionDisplayInfo (and formatTimestamp below) are near byte-for-byte copies of the Console's packages/console/src/pages/UserDetails/UserSettings/UserSessions/utils.ts + UserSessionDetails. normalizeGrantRows likewise duplicates Console's use-user-third-party-grants.ts. These are pure functions whose only non-trivial dep (userSessionSignInContextGuard) is in @logto/schemas, and both apps already import @logto/shared/universal — so this could move there and be shared. The copies have already drifted (Console surfaces city/country; this one drops them), so fixes will otherwise land in only one place.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed — these are near-identical pure functions. Moving them to @logto/shared/universal (which both apps already import) would eliminate the drift risk. Filed as a follow-up since it touches Console code too.


const timestamp = value < 1_000_000_000_000 ? value * 1000 : value;

return new Date(timestamp).toLocaleString();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

toLocaleString() is called with no locale, so timestamps won't follow the user's selected UI language (the Console grant formatter passes i18n.language, and account-center already has utils/date.ts getDateFnsLocale for this). Given the PR ships 18 locales, dates will render in the runtime default rather than the chosen language. Same applies to line 132.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed — formatTimestamp now accepts a language parameter and uses date-fns format(date, 'PPp', { locale: getDateFnsLocale(language) }), consistent with PasskeyView. Both SessionRow and GrantRow pass i18n.language. Also changed GrantedAppRow.createdAt to iat (numeric) so formatting happens in the component with the correct locale.

const SessionRow = ({ session, isEditable, isCurrent, onRevoke }: SessionRowProps) => {
const { t } = useTranslation();

const { name, location, ip } = getSessionDisplayInfo(session);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When getSessionDisplayInfo returns {} — which happens whenever lastSubmission is null (a schema-legal state, the guard is .nullable()) or signInContext is missing — deviceName collapses to - and the meta line is empty. A user with several older sessions then sees multiple identical - rows and can't tell which device they're revoking. Consider a more identifying fallback (e.g. IP, or signed-in date emphasized).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed — when name is undefined (no signInContext or UA parse fails), the fallback chain is now name ?? ip ?? signedInAt, so the row always shows something identifying.

}

return Array.from(groupedByApplicationId.entries())
.slice()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: .slice() here is a no-op — Array.from(...) already returns a fresh array, so there's nothing to copy/protect before .sort(). (Carried over from the Console copy.) Can be removed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Kept .slice() — it's semantically a no-op after Array.from(), but the @silverhand/fp/no-mutating-methods ESLint rule requires it (it can't statically prove the array is fresh).

Comment thread packages/account/src/App.tsx Outdated
const hideLogtoBranding = experienceSettings?.hideLogtoBranding === true;
const { pathname } = useLocation();
const showsSecurityPage = hasVisibleSecuritySection(accountCenterSettings, experienceSettings);
const showsSessionsPage = isDevFeaturesEnabled && hasVisibleSessionsPage(accountCenterSettings);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: showsSessionsPage = isDevFeaturesEnabled && hasVisibleSessionsPage(...) is computed identically here and in Main (line 134), and the isDevFeaturesEnabled dev-gate is now scattered across routes + nav. Folding the dev-gate into hasVisibleSessionsPage (or one derived value) avoids the "nav shows but route 404s" failure mode when sessions graduate out of dev features.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed — folded isDevFeaturesEnabled into hasVisibleSessionsPage in security-page.ts. Both call sites in App.tsx (Main + Layout) now just call hasVisibleSessionsPage(accountCenterSettings) without the separate dev-gate.

case 'remove-social': {
return accountCenterSettings.fields.social === AccountCenterControlValue.Edit;
}
case 'load-sessions': {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: this load-sessions gate checks only fields.session !== Off, with no isDevFeaturesEnabled guard — unlike the Sessions route/nav in App.tsx. Latent only today (the sole writer of the flag is the dev-gated Sessions page), but a stale sessionStorage flag from a prior dev-enabled session would be treated as allowed while the route doesn't exist.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed — added isDevFeaturesEnabled guard to the load-sessions case.

…, locale-aware dates

- Parallel fetch sessions and grants with Promise.all
- Collapse two useEffects into a single load effect with ref guard to prevent double-fetch race
- Use date-fns format with locale for timestamps instead of bare toLocaleString()
- Always show grants section after load (grantRows undefined falls through to empty state)
- Better SessionRow fallback: show IP or sign-in date when device info unavailable
- Fold isDevFeaturesEnabled into hasVisibleSessionsPage to centralize the dev gate
- Add isDevFeaturesEnabled guard to load-sessions case in VerifiedAction
- Change GrantedAppRow.createdAt to iat (numeric) for locale-aware formatting in component
Copilot AI review requested due to automatic review settings June 8, 2026 04:17
@github-actions github-actions Bot added size/xl and removed size/xl labels Jun 8, 2026
Copy link
Copy Markdown
Contributor

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

Copilot reviewed 34 out of 35 changed files in this pull request and generated 2 comments.

Comment on lines +260 to +266
{hasLoaded && (
<div className={classNames(styles.section, layoutClassNames.section)}>
<div className={classNames(styles.sectionTitle, layoutClassNames.sectionTitle)}>
{t('account_center.sessions.third_party_apps_title')}
</div>
<div className={classNames(styles.card, layoutClassNames.card)}>
{grantRows && grantRows.length > 0 ? (
Comment on lines +55 to +60
export const hasVisibleSessionsPage = (accountCenterSettings?: SecurityPageSettings): boolean => {
if (!isDevFeaturesEnabled || !accountCenterSettings?.enabled) {
return false;
}

return isVisibleField(accountCenterSettings.fields.session);
@github-actions github-actions Bot added size/xl and removed size/xl labels Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

3 participants