Skip to content

[Web Import] Add persistent settings for font customization#899

Merged
egorikftp merged 1 commit intomainfrom
feature/idea/material-save-settings
Feb 25, 2026
Merged

[Web Import] Add persistent settings for font customization#899
egorikftp merged 1 commit intomainfrom
feature/idea/material-save-settings

Conversation

@egorikftp
Copy link
Member

@egorikftp egorikftp commented Feb 24, 2026

Screen.Recording.2026-02-24.at.18.19.01.mov

📝 Changelog

If this PR introduces user-facing changes, please update the relevant Unreleased section in changelogs:

@coderabbitai
Copy link

coderabbitai bot commented Feb 24, 2026

Walkthrough

This PR renames Material symbol types (FontSettings → MaterialFontSettings, IconFontFamily → MaterialIconFontFamily) and updates their usages across UI, view models, repositories, and use cases. It adds Material font state properties plus lucide/bootstrap size properties to PersistentSettings, introduces a generic readState helper in InMemorySettings, and wires InMemorySettings into use cases via DI to persist font and size settings. It removes logging from StandardIconViewModel and replaces the deleted FontSettings file with MaterialFontSettings and a revised MaterialIconFontFamily enum.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main change: adding persistent settings for font customization in the Web Import feature, which directly addresses the core objective.
Description check ✅ Passed The PR description identifies the closed issue (#897), includes a video demonstration, and confirms the IntelliJ Plugin changelog was updated as required by the template.
Linked Issues check ✅ Passed The PR implements persistent settings for font customization across all icon providers (Material Symbols, Bootstrap, Lucide) and includes the fill state persistence requested in issue #897, exceeding the core requirement.
Out of Scope Changes check ✅ Passed All changes align with the stated objective of adding persistent font customization settings. Refactoring of font-related types and removal of logging in StandardIconViewModel are necessary implementation details supporting the persistence feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/idea/material-save-settings

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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.

🧹 Nitpick comments (3)
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt (1)

22-23: isModified check for fill is implicitly coupled to DEFAULT_FILL = false.

Using fill (truthy check) instead of fill != DEFAULT_FILL works only because DEFAULT_FILL is false. If the default ever changes to true, this will silently report modifications incorrectly. Consider using fill != DEFAULT_FILL for consistency with the other fields.

♻️ Suggested change
     val isModified: Boolean
-        get() = fill || weight != DEFAULT_WEIGHT || grade != DEFAULT_GRADE || opticalSize != DEFAULT_OPTICAL_SIZE
+        get() = fill != DEFAULT_FILL || weight != DEFAULT_WEIGHT || grade != DEFAULT_GRADE || opticalSize != DEFAULT_OPTICAL_SIZE
🤖 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/material/domain/model/font/MaterialFontSettings.kt`
around lines 22 - 23, The isModified getter currently uses a truthy check for
fill which assumes DEFAULT_FILL == false; change the comparison to explicitly
compare fill != DEFAULT_FILL so it is consistent with the other fields (weight
!= DEFAULT_WEIGHT, grade != DEFAULT_GRADE, opticalSize != DEFAULT_OPTICAL_SIZE)
and will remain correct if DEFAULT_FILL changes; update the isModified
expression to use fill != DEFAULT_FILL alongside the existing comparisons
referencing DEFAULT_WEIGHT, DEFAULT_GRADE, and DEFAULT_OPTICAL_SIZE.
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/common/ui/SidePanel.kt (1)

23-24: Consider whether common/ui/SidePanel preview should depend on material/ types.

The SidePanel composable is generic (accepts content: @composable () -> Unit), but its preview imports MaterialFontCustomization and MaterialFontSettings from the material package. This creates a dependency from a common UI component's preview on a specific feature module. A simpler placeholder content (e.g., a plain Text) would keep this preview independent.

This is a pre-existing pattern (just renamed), so no action needed now.

Also applies to: 84-86

🤖 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/common/ui/SidePanel.kt`
around lines 23 - 24, The SidePanel preview currently depends on
material-specific types (MaterialFontCustomization, MaterialFontSettings);
replace that preview content with a minimal placeholder (e.g., a plain Text
composable) and remove the imports of MaterialFontCustomization and
MaterialFontSettings so the SidePanel preview no longer references the material/
feature module; update both preview usages (the one around SidePanel and the
second instance referenced at lines 84-86) to use the simple placeholder content
instead.
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsViewModel.kt (1)

180-192: Minor dispatcher inconsistency with LucideViewModel.updateSettings.

LucideViewModel.updateSettings (line 154) launches with Dispatchers.Default, while MaterialSymbolsViewModel.updateFontSettings uses the default dispatcher (Main). Both work fine since inMemorySettings.update is lightweight, but it's a small inconsistency.

♻️ Align dispatcher usage
     fun updateFontSettings(fontSettings: MaterialFontSettings) {
-        viewModelScope.launch {
+        viewModelScope.launch(Dispatchers.Default) {
             inMemorySettings.update {
🤖 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/material/MaterialSymbolsViewModel.kt`
around lines 180 - 192, The two view models use different coroutine dispatchers:
MaterialSymbolsViewModel.updateFontSettings currently uses viewModelScope.launch
(Main) while LucideViewModel.updateSettings uses
viewModelScope.launch(Dispatchers.Default); make them consistent by launching
updateFontSettings with viewModelScope.launch(Dispatchers.Default) and perform
inMemorySettings.update and updateSuccess within that dispatcher (keeping
function names MaterialSymbolsViewModel.updateFontSettings,
inMemorySettings.update, and updateSuccess to locate the changes).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/common/ui/SidePanel.kt`:
- Around line 23-24: The SidePanel preview currently depends on
material-specific types (MaterialFontCustomization, MaterialFontSettings);
replace that preview content with a minimal placeholder (e.g., a plain Text
composable) and remove the imports of MaterialFontCustomization and
MaterialFontSettings so the SidePanel preview no longer references the material/
feature module; update both preview usages (the one around SidePanel and the
second instance referenced at lines 84-86) to use the simple placeholder content
instead.

In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt`:
- Around line 22-23: The isModified getter currently uses a truthy check for
fill which assumes DEFAULT_FILL == false; change the comparison to explicitly
compare fill != DEFAULT_FILL so it is consistent with the other fields (weight
!= DEFAULT_WEIGHT, grade != DEFAULT_GRADE, opticalSize != DEFAULT_OPTICAL_SIZE)
and will remain correct if DEFAULT_FILL changes; update the isModified
expression to use fill != DEFAULT_FILL alongside the existing comparisons
referencing DEFAULT_WEIGHT, DEFAULT_GRADE, and DEFAULT_OPTICAL_SIZE.

In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsViewModel.kt`:
- Around line 180-192: The two view models use different coroutine dispatchers:
MaterialSymbolsViewModel.updateFontSettings currently uses viewModelScope.launch
(Main) while LucideViewModel.updateSettings uses
viewModelScope.launch(Dispatchers.Default); make them consistent by launching
updateFontSettings with viewModelScope.launch(Dispatchers.Default) and perform
inMemorySettings.update and updateSuccess within that dispatcher (keeping
function names MaterialSymbolsViewModel.updateFontSettings,
inMemorySettings.update, and updateSuccess to locate the changes).

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd2df46 and 9aff2cb.

📒 Files selected for processing (15)
  • tools/idea-plugin/CHANGELOG.md
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.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/common/ui/SidePanel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/lucide/LucideViewModel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsImportScreen.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsViewModel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/data/font/MaterialFontRepository.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/MaterialSymbolsConfigUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/FontSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialIconFontFamily.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontCustomization.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontFamilyDropdown.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialTopActions.kt
💤 Files with no reviewable changes (1)
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/FontSettings.kt

@egorikftp egorikftp force-pushed the feature/idea/material-save-settings branch from 9aff2cb to 0855840 Compare February 24, 2026 16:01
Copy link

@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.

🧹 Nitpick comments (1)
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsViewModel.kt (1)

213-221: Add default value to fontSettings parameter in MaterialState.Success

fontSettings: MaterialFontSettings has no default value while surrounded by selectedCategory (which defaults to Category.All) and iconFontFamily (which defaults to MaterialIconFontFamily.Outlined). Since all fields of MaterialFontSettings carry default values, MaterialFontSettings() is a valid no-arg call. Adding a default here aligns with Kotlin conventions for parameter ordering.

Proposed fix
-    val fontSettings: MaterialFontSettings,
+    val fontSettings: MaterialFontSettings = MaterialFontSettings(),
🤖 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/material/MaterialSymbolsViewModel.kt`
around lines 213 - 221, The Success variant of MaterialState declares
fontSettings: MaterialFontSettings without a default while neighboring params
have defaults; update the data class MaterialState.Success to give fontSettings
a default value by using MaterialFontSettings() so callers can omit it (i.e.,
change the constructor param in Success to fontSettings: MaterialFontSettings =
MaterialFontSettings()) and keep other defaults (selectedCategory,
iconFontFamily, fontByteArray) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsViewModel.kt`:
- Around line 213-221: The Success variant of MaterialState declares
fontSettings: MaterialFontSettings without a default while neighboring params
have defaults; update the data class MaterialState.Success to give fontSettings
a default value by using MaterialFontSettings() so callers can omit it (i.e.,
change the constructor param in Success to fontSettings: MaterialFontSettings =
MaterialFontSettings()) and keep other defaults (selectedCategory,
iconFontFamily, fontByteArray) unchanged.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9aff2cb and 0855840.

📒 Files selected for processing (15)
  • tools/idea-plugin/CHANGELOG.md
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.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/common/ui/SidePanel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/lucide/LucideViewModel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsImportScreen.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsViewModel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/data/font/MaterialFontRepository.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/MaterialSymbolsConfigUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/FontSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialIconFontFamily.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontCustomization.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontFamilyDropdown.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialTopActions.kt
💤 Files with no reviewable changes (1)
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/FontSettings.kt
🚧 Files skipped from review as they are similar to previous changes (5)
  • tools/idea-plugin/CHANGELOG.md
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialIconFontFamily.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/MaterialSymbolsConfigUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialTopActions.kt

@egorikftp egorikftp force-pushed the feature/idea/material-save-settings branch from 0855840 to e3a8917 Compare February 24, 2026 18:17
@egorikftp egorikftp force-pushed the feature/idea/material-save-settings branch from e3a8917 to 6a6a96c Compare February 25, 2026 07:52
@egorikftp egorikftp requested a review from t-regbs February 25, 2026 07:53
Copy link

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/data/font/MaterialFontRepository.kt (1)

32-50: ⚠️ Potential issue | 🟠 Major

Handle empty icon option when only optical size changes.

Line 33 allows the modified path, but Lines 38-49 can still return an empty option when only opticalSize differs. That leads to an invalid URL segment and failed SVG download.

Proposed fix
 private fun MaterialFontSettings.iconOption(): String {
     if (!isModified) {
         return "default"
     }

-    return buildString {
+    val option = buildString {
         if (weight != 400) {
             append("wght$weight")
         }
         if (grade != 0) {
             when {
                 grade < 0 -> append("gradN${abs(grade)}")
                 else -> append("grad$grade")
             }
         }
         if (fill) {
             append("fill1")
         }
     }
+    return option.ifEmpty { "default" }
 }
🤖 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/material/data/font/MaterialFontRepository.kt`
around lines 32 - 50, In MaterialFontSettings.iconOption(), when isModified is
true the buildString block can still produce an empty string (for example if
only opticalSize changed), which yields an invalid URL segment; update the
method so that after constructing the option string (using weight, grade, fill,
etc.) you check if the built string is blank/empty and return "default" in that
case (instead of an empty string); refer to the MaterialFontSettings.iconOption
function and the variables weight, grade, fill, opticalSize and isModified to
implement this guard.
🤖 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/bootstrap/domain/BootstrapUseCase.kt`:
- Around line 23-29: persistentSize is currently a one-time initialized val
using inMemorySettings.readState and becomes stale after updatePersistentSize
mutates state; change persistentSize to a getter (e.g., override val
persistentSize: Int get() = inMemorySettings.readState { bootstrapSize }) so
every access reads the current state, and apply the same change for the
analogous property in LucideUseCase; keep updatePersistentSize implementation
(which calls inMemorySettings.update { bootstrapSize = value }) unchanged.

---

Outside diff comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/data/font/MaterialFontRepository.kt`:
- Around line 32-50: In MaterialFontSettings.iconOption(), when isModified is
true the buildString block can still produce an empty string (for example if
only opticalSize changed), which yields an invalid URL segment; update the
method so that after constructing the option string (using weight, grade, fill,
etc.) you check if the built string is blank/empty and return "default" in that
case (instead of an empty string); refer to the MaterialFontSettings.iconOption
function and the variables weight, grade, fill, opticalSize and isModified to
implement this guard.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0855840 and 6a6a96c.

📒 Files selected for processing (20)
  • tools/idea-plugin/CHANGELOG.md
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.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/common/ui/SidePanel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsImportScreen.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsViewModel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/data/font/MaterialFontRepository.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/MaterialSymbolsConfigUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/FontSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialIconFontFamily.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontCustomization.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontFamilyDropdown.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialTopActions.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/StandardIconViewModel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/bootstrap/di/BootstrapModule.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/bootstrap/domain/BootstrapUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/domain/StandardIconProvider.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/lucide/di/LucideModule.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/lucide/domain/LucideUseCase.kt
💤 Files with no reviewable changes (1)
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/FontSettings.kt
🚧 Files skipped from review as they are similar to previous changes (3)
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt
  • tools/idea-plugin/CHANGELOG.md
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialTopActions.kt

@egorikftp egorikftp force-pushed the feature/idea/material-save-settings branch from 6a6a96c to 82f05eb Compare February 25, 2026 09:58
Copy link

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/data/font/MaterialFontRepository.kt (1)

32-51: ⚠️ Potential issue | 🔴 Critical

iconOption() can return an empty string, producing a malformed URL when only opticalSize is non-default.

isModified includes opticalSize in its check, so if the user changes only optical size (e.g. fill=false, weight=400, grade=0, opticalSize=36f), isModified is true and the "default" early-return is skipped. But the buildString block only handles weight, grade, and fill — none of which deviate — so it produces an empty String. The resulting URL becomes:

https://fonts.gstatic.com/s/i/short-term/release/$fontFamily/$name//$iconSize.svg

...with a double slash, which is an invalid resource path.

🐛 Proposed fix — fall back to `"default"` when the built string is empty
-    private fun MaterialFontSettings.iconOption(): String {
-        if (!isModified) {
-            return "default"
-        }
-
-        return buildString {
-            if (weight != 400) {
-                append("wght$weight")
-            }
-            if (grade != 0) {
-                when {
-                    grade < 0 -> append("gradN${abs(grade)}")
-                    else -> append("grad$grade")
-                }
-            }
-            if (fill) {
-                append("fill1")
-            }
-        }
-    }
+    private fun MaterialFontSettings.iconOption(): String {
+        return buildString {
+            if (weight != DEFAULT_WEIGHT) {
+                append("wght$weight")
+            }
+            if (grade != DEFAULT_GRADE) {
+                when {
+                    grade < 0 -> append("gradN${abs(grade)}")
+                    else -> append("grad$grade")
+                }
+            }
+            if (fill) {
+                append("fill1")
+            }
+        }.ifEmpty { "default" }
+    }

This removes the isModified gate (which incorrectly includes opticalSize) and instead lets buildString run always, falling back to "default" only when the relevant options produce an empty string.

🤖 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/material/data/font/MaterialFontRepository.kt`
around lines 32 - 51, MaterialFontSettings.iconOption() can produce an empty
string (causing a malformed URL) when only opticalSize is changed; fix by
ensuring the method returns "default" whenever the constructed string is empty:
run the existing buildString logic (or keep the current isModified check) but
after building the string check if the result is blank/empty and return
"default" in that case; update the MaterialFontSettings.iconOption()
implementation so callers (e.g., URL construction using iconOption()) never
receive an empty string.
🧹 Nitpick comments (1)
tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt (1)

5-27: LGTM — clean model with sensible defaults and range validation.

One note: the isModified getter at Line 26 uses fill || as a shorthand for fill != DEFAULT_FILL (which holds because DEFAULT_FILL = false). This is correct, but it's worth knowing that this expression ties isModified semantics to the specific default value of fill. If DEFAULT_FILL ever changes to true, isModified would silently break (a non-filled state would incorrectly appear as "modified" when fill == true is the new default). Consider fill != DEFAULT_FILL || ... for robustness.

✏️ Suggested fix for future-proofing `isModified`
-    override val isModified: Boolean
-        get() = fill || weight != DEFAULT_WEIGHT || grade != DEFAULT_GRADE || opticalSize != DEFAULT_OPTICAL_SIZE
+    override val isModified: Boolean
+        get() = fill != DEFAULT_FILL || weight != DEFAULT_WEIGHT || grade != DEFAULT_GRADE || opticalSize != DEFAULT_OPTICAL_SIZE
🤖 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/material/domain/model/font/MaterialFontSettings.kt`
around lines 5 - 27, Update the isModified getter in MaterialFontSettings to
compare fill against DEFAULT_FILL explicitly (use fill != DEFAULT_FILL) instead
of relying on the current boolean literal; keep the other comparisons (weight !=
DEFAULT_WEIGHT, grade != DEFAULT_GRADE, opticalSize != DEFAULT_OPTICAL_SIZE)
as-is so isModified remains robust if DEFAULT_FILL changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/data/font/MaterialFontRepository.kt`:
- Around line 32-51: MaterialFontSettings.iconOption() can produce an empty
string (causing a malformed URL) when only opticalSize is changed; fix by
ensuring the method returns "default" whenever the constructed string is empty:
run the existing buildString logic (or keep the current isModified check) but
after building the string check if the result is blank/empty and return
"default" in that case; update the MaterialFontSettings.iconOption()
implementation so callers (e.g., URL construction using iconOption()) never
receive an empty string.

---

Nitpick comments:
In
`@tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt`:
- Around line 5-27: Update the isModified getter in MaterialFontSettings to
compare fill against DEFAULT_FILL explicitly (use fill != DEFAULT_FILL) instead
of relying on the current boolean literal; keep the other comparisons (weight !=
DEFAULT_WEIGHT, grade != DEFAULT_GRADE, opticalSize != DEFAULT_OPTICAL_SIZE)
as-is so isModified remains robust if DEFAULT_FILL changes.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a6a96c and 82f05eb.

📒 Files selected for processing (20)
  • tools/idea-plugin/CHANGELOG.md
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.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/common/ui/SidePanel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsImportScreen.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/MaterialSymbolsViewModel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/data/font/MaterialFontRepository.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/MaterialSymbolsConfigUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/FontSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialFontSettings.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialIconFontFamily.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontCustomization.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontFamilyDropdown.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialTopActions.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/StandardIconViewModel.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/bootstrap/di/BootstrapModule.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/bootstrap/domain/BootstrapUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/domain/StandardIconProvider.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/lucide/di/LucideModule.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/lucide/domain/LucideUseCase.kt
💤 Files with no reviewable changes (1)
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/FontSettings.kt
🚧 Files skipped from review as they are similar to previous changes (7)
  • tools/idea-plugin/CHANGELOG.md
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/bootstrap/di/BootstrapModule.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/lucide/di/LucideModule.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/MaterialSymbolsConfigUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/standard/bootstrap/domain/BootstrapUseCase.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/ui/MaterialFontCustomization.kt
  • tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/webimport/material/domain/model/font/MaterialIconFontFamily.kt

@egorikftp egorikftp merged commit 24aff8d into main Feb 25, 2026
3 checks passed
@egorikftp egorikftp deleted the feature/idea/material-save-settings branch February 25, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Please add 'memorizing fill state' in Material Symbols import

2 participants