Conversation
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
WalkthroughAdds Font Awesome support and related infrastructure: updates version catalog with 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardIconViewModel.kt (1)
215-231: Per-style prefetch re-loads shared-font providers.This loop keys the cache by style id, but
BoxIconsUseCase.loadFontBytes()intools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/boxicons/domain/BoxIconsUseCase.ktignores the style and always fetches the same font. Opening BoxIcons will now schedule the same font load for regular, solid, and logos, then keep three copies of identical bytes in memory. Consider letting providers expose a shared font-cache key or opt out of prefetch when styles reuse one font.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardIconViewModel.kt` around lines 215 - 231, prefetchStyleFonts is caching font bytes by style.id but provider.loadFontBytes (e.g., BoxIconsUseCase.loadFontBytes) returns the same shared font for multiple styles, causing duplicate cached byte arrays; change the prefetch logic to use a provider-level font cache key (e.g., provider.fontCacheKey or provider.getFontKey(style)) or skip prefetch for styles that map to the same key: compute a unique fontKey for each style (call provider method or add one to the provider interface), check fontCache[fontKey] instead of fontCache[style.id], and only call provider.loadFontBytes(style) when that fontKey is not already cached so identical fonts are fetched/stored once.tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt (1)
64-72: WOFF2 decoding failure path propagates an opaque error.When
Woff2Decoder.decodeBytesreturnsnull, the genericerror()message provides no context about which font failed. Consider including the URL or style ID in the error message to aid debugging.🔧 Proposed improvement
private suspend fun loadAndDecodeWoff2(url: String): ByteArray { return withContext(Dispatchers.IO) { val woff2Bytes = httpClient.get(url).bodyAsChannel().toByteArray() withContext(Dispatchers.Default) { - Woff2Decoder.decodeBytes(woff2Bytes) ?: error("Failed to decode WOFF2 font") + Woff2Decoder.decodeBytes(woff2Bytes) + ?: error("Failed to decode WOFF2 font from: $url") } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt` around lines 64 - 72, In loadAndDecodeWoff2, when Woff2Decoder.decodeBytes(woff2Bytes) returns null replace the opaque error() call with an error message that includes identifying context (at minimum the url, and optionally a style or font id if available) so failures show which font failed to decode; update the thrown exception message to include url and the fact decoding returned null and keep this change scoped to loadAndDecodeWoff2 and the decodeBytes result handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardIconViewModel.kt`:
- Around line 48-67: In the StandardState.Success branch adjust handling of
initialState.fontByteArray so we only reuse/cache it when the saved style
matches the normalizedSelectedStyle: compute normalizedSelectedStyle as you
already do, then if initialState.fontByteArray != null check that
initialState.selectedStyle?.id == normalizedSelectedStyle?.id before storing
into fontCache (fontCache[styleKey] = it); otherwise clear/ignore
initialState.fontByteArray and call downloadFont(normalizedSelectedStyle) to
force re-download; update the logic around downloadFont(normalizedSelectedStyle)
and fontByteArray to reflect this conditional.
- Around line 170-187: selectStyle currently reads the shared mutable map
fontCache inside viewModelScope.launch(Dispatchers.Default), causing potential
data races because other reads/writes (around updateSuccess and downloadFont)
happen on the main dispatcher; fix by either (A) switching the cache read to run
on Dispatchers.Main (e.g., perform fontCache[style.id] lookup inside a
withContext(Dispatchers.Main) block before calling updateSuccess and
downloadFont) or (B) make fontCache thread-safe (replace mutableMapOf with a
synchronized map or guard all accesses to fontCache with a Mutex) so that the
lookup in selectStyle and writes in downloadFont are safely synchronized.
---
Nitpick comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardIconViewModel.kt`:
- Around line 215-231: prefetchStyleFonts is caching font bytes by style.id but
provider.loadFontBytes (e.g., BoxIconsUseCase.loadFontBytes) returns the same
shared font for multiple styles, causing duplicate cached byte arrays; change
the prefetch logic to use a provider-level font cache key (e.g.,
provider.fontCacheKey or provider.getFontKey(style)) or skip prefetch for styles
that map to the same key: compute a unique fontKey for each style (call provider
method or add one to the provider interface), check fontCache[fontKey] instead
of fontCache[style.id], and only call provider.loadFontBytes(style) when that
fontKey is not already cached so identical fonts are fetched/stored once.
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt`:
- Around line 64-72: In loadAndDecodeWoff2, when
Woff2Decoder.decodeBytes(woff2Bytes) returns null replace the opaque error()
call with an error message that includes identifying context (at minimum the
url, and optionally a style or font id if available) so failures show which font
failed to decode; update the thrown exception message to include url and the
fact decoding returned null and keep this change scoped to loadAndDecodeWoff2
and the decodeBytes result handling.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d8c4a5b6-6708-41d8-9690-d73cae0cbf2e
📒 Files selected for processing (30)
gradle/libs.versions.tomlsdk/compose/icons/api/icons.apisdk/compose/icons/api/icons.klib.apisdk/compose/icons/src/commonMain/kotlin/io/github/composegears/valkyrie/sdk/compose/icons/colored/FontAwesomeLogo.kttools/idea-plugin/CHANGELOG.mdtools/idea-plugin/build.gradle.ktstools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/settings/InMemorySettings.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/WebImportFlow.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/WebImportSelectorScreen.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/bootstrap/domain/BootstrapUseCase.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/boxicons/domain/BoxIconsUseCase.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardIconViewModel.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardImportScreenUI.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/domain/StandardIconProvider.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/model/StandardIconConfig.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/util/StandardGridFiltering.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/FontAwesomeImportScreen.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeCategoriesYamlParser.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeIconMetadata.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeIconsYamlParser.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeYamlUtil.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/di/FontAwesomeModule.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/domain/FontAwesomeUseCase.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/lucide/domain/LucideUseCase.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/remix/domain/RemixUseCase.kttools/idea-plugin/src/main/resources/messages/Valkyrie.propertiestools/idea-plugin/src/test/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeCategoriesYamlParserTest.kttools/idea-plugin/src/test/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeIconsYamlParserTest.kt
💤 Files with no reviewable changes (1)
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/model/StandardIconConfig.kt
...io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardIconViewModel.kt
Show resolved
Hide resolved
...io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardIconViewModel.kt
Show resolved
Hide resolved
|
|
||
| ## Unreleased | ||
|
|
||
| - [Web Import] Add `Font Awesome` icons provider |
There was a problem hiding this comment.
Please add into ### Added section
| companion object { | ||
| private const val CDN_BASE = "https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@latest" | ||
| private const val ICONS_YML_URL = "$CDN_BASE/metadata/icons.yml" | ||
| private const val CATEGORIES_YML_URL = "$CDN_BASE/metadata/categories.yml" |
There was a problem hiding this comment.
They have css files splitted by category
https://www.npmjs.com/package/@fortawesome/fontawesome-free?activeTab=code
There was a problem hiding this comment.
I will blame it on working late but I thought there was no solid.css files there.
At the moment I'm using:
- icons.yml for codepoints, search terms, and styles
- categories.yml for category grouping
So I think the main question is which direction we want here:
- Use CSS for codepoint/style extraction to stay consistent with the other providers, but keep YAML for categories.
- Use CSS only, and fall back to inferred names/categories/tags where needed.
I lean toward keeping the YAML categories personally but happy to remove it completely too, what do you think?
There was a problem hiding this comment.
Well, I checked again and looks like css files not contains all necessary info
...composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt (1)
20-20: Consider pinning a specific Font Awesome version.Using
@latestmakes builds non-reproducible and could break unexpectedly if Font Awesome changes their CDN structure or YAML schema. If stability is a concern, consider pinning a specific version (e.g.,@6.5.1) and updating it periodically.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt` at line 20, The CDN_BASE constant in FontAwesomeRepository currently uses the non-reproducible "@latest" tag; change CDN_BASE to reference a specific Font Awesome release (e.g., "@6.5.1") to pin the dependency and ensure reproducible builds, or make the version configurable via a VERSION constant or constructor parameter so updates are deliberate and tracked (update the CDN_BASE declaration in FontAwesomeRepository accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt`:
- Around line 51-54: loadFontBytes currently silently falls back to
SOLID_STYLE_ID when an unknown styleId is passed; update loadFontBytes to handle
invalid style IDs explicitly by checking fontsByStyleId.containsKey(styleId) and
either (A) throw an IllegalArgumentException (or custom exception) referencing
the invalid styleId, or (B) log a warning via the existing logger that styleId
is unknown and you are falling back to SOLID_STYLE_ID before calling the loader;
make the change inside loadFontBytes and keep the existing fallback behavior
only if you choose the logging option.
---
Nitpick comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt`:
- Line 20: The CDN_BASE constant in FontAwesomeRepository currently uses the
non-reproducible "@latest" tag; change CDN_BASE to reference a specific Font
Awesome release (e.g., "@6.5.1") to pin the dependency and ensure reproducible
builds, or make the version configurable via a VERSION constant or constructor
parameter so updates are deliberate and tracked (update the CDN_BASE declaration
in FontAwesomeRepository accordingly).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d56aae9e-9e14-46fe-88a8-aabcbad85ace
📒 Files selected for processing (2)
tools/idea-plugin/CHANGELOG.mdtools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt
🚧 Files skipped from review as they are similar to previous changes (1)
- tools/idea-plugin/CHANGELOG.md
...composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt
Show resolved
Hide resolved
5ae592f to
bd5649c
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardImportScreenUI.kt (1)
240-243: Consider moving alias resolution into the provider contract.
"$fontAlias-${style.id}"adds a second implicit style-to-font mapping rule in the UI. A smallresolveFontAlias(style)helper onStandardIconProviderwould keep that contract in one place and avoid future drift.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardImportScreenUI.kt` around lines 240 - 243, The UI is constructing a style-aware alias inline via "$fontAlias-${style.id}" which duplicates mapping logic; add a resolveFontAlias(style) (or resolveFontAlias(fontAlias, style)) helper to the StandardIconProvider contract and replace the inline logic in StandardImportScreenUI where styleAwareAlias is computed (using state.selectedStyle and fontAlias) with a call to that provider method so alias resolution lives in the provider API and not in the UI.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kt`:
- Around line 20-28: The CDN_BASE constant currently uses "@latest", which risks
inconsistent upstream changes across ICONS_YML_URL, CATEGORIES_YML_URL,
FONT_SOLID, FONT_REGULAR and FONT_BRANDS; change CDN_BASE to reference a
concrete, tested Font Awesome release (e.g., replace "@latest" with a pinned
version string) so all derived constants (ICONS_YML_URL, CATEGORIES_YML_URL,
FONT_SOLID, FONT_REGULAR, FONT_BRANDS) resolve to the same version, and consider
introducing a single VERSION constant to make future updates intentional and
visible.
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/domain/FontAwesomeUseCase.kt`:
- Around line 34-36: The resolveFontWeight implementation is inconsistent with
loadFontBytes: it maps a null IconStyle to W400 while loadFontBytes treats null
as the solid style; update resolveFontWeight (function resolveFontWeight in
FontAwesomeUseCase) so that when style is null it returns FontWeight.W900 (same
as when style?.id == SOLID_STYLE_ID) instead of W400, ensuring glyph selection
matches loadFontBytes' null-as-solid behavior.
---
Nitpick comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardImportScreenUI.kt`:
- Around line 240-243: The UI is constructing a style-aware alias inline via
"$fontAlias-${style.id}" which duplicates mapping logic; add a
resolveFontAlias(style) (or resolveFontAlias(fontAlias, style)) helper to the
StandardIconProvider contract and replace the inline logic in
StandardImportScreenUI where styleAwareAlias is computed (using
state.selectedStyle and fontAlias) with a call to that provider method so alias
resolution lives in the provider API and not in the UI.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 8fcecf95-26f3-4a46-b9f9-d7f6ff8f850e
📒 Files selected for processing (30)
gradle/libs.versions.tomlsdk/compose/icons/api/icons.apisdk/compose/icons/api/icons.klib.apisdk/compose/icons/src/commonMain/kotlin/io/github/composegears/valkyrie/sdk/compose/icons/colored/FontAwesomeLogo.kttools/idea-plugin/CHANGELOG.mdtools/idea-plugin/build.gradle.ktstools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/settings/InMemorySettings.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/WebImportFlow.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/WebImportSelectorScreen.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/bootstrap/domain/BootstrapUseCase.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/boxicons/domain/BoxIconsUseCase.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardIconViewModel.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/StandardImportScreenUI.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/domain/StandardIconProvider.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/model/StandardIconConfig.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/util/StandardGridFiltering.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/FontAwesomeImportScreen.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeCategoriesYamlParser.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeIconMetadata.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeIconsYamlParser.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeRepository.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeYamlUtil.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/di/FontAwesomeModule.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/domain/FontAwesomeUseCase.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/lucide/domain/LucideUseCase.kttools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/remix/domain/RemixUseCase.kttools/idea-plugin/src/main/resources/messages/Valkyrie.propertiestools/idea-plugin/src/test/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeCategoriesYamlParserTest.kttools/idea-plugin/src/test/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeIconsYamlParserTest.kt
💤 Files with no reviewable changes (1)
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/model/StandardIconConfig.kt
🚧 Files skipped from review as they are similar to previous changes (8)
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.kt
- tools/idea-plugin/src/main/resources/messages/Valkyrie.properties
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/remix/domain/RemixUseCase.kt
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/common/domain/StandardIconProvider.kt
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/lucide/domain/LucideUseCase.kt
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeIconMetadata.kt
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/settings/InMemorySettings.kt
- tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/fontawesome/data/FontAwesomeCategoriesYamlParser.kt

Screen.Recording.2026-03-06.at.00.16.36.mov
📝 Changelog
If this PR introduces user-facing changes, please update the relevant Unreleased section in changelogs: