Skip to content

Add source icons on resource covers for non-filesystem sources#1015

Closed
anobaka wants to merge 74 commits intomainfrom
claude/add-source-icons-S19RG
Closed

Add source icons on resource covers for non-filesystem sources#1015
anobaka wants to merge 74 commits intomainfrom
claude/add-source-icons-S19RG

Conversation

@anobaka
Copy link
Copy Markdown
Owner

@anobaka anobaka commented Mar 25, 2026

Summary

  • Displays the corresponding source icon (Steam, DLsite, ExHentai) in the bottom-right corner of resource cover images when the resource comes from a non-FileSystem source
  • Icon is shown in a semi-transparent dark badge for visibility against any cover image
  • Reuses the existing ResourceSourceIcon component

Changes

  • ResourceCover/index.tsx: Added source icon overlay rendering for non-FileSystem resources
  • ResourceCover/index.scss: Added .source-icon-overlay styles (positioned bottom-right, rounded badge with dark background)

Test plan

  • Verify Steam resources show the Steam icon on their cover
  • Verify DLsite resources show the DLsite icon on their cover
  • Verify ExHentai resources show the ExHentai icon on their cover
  • Verify FileSystem resources do NOT show any source icon
  • Verify the icon does not interfere with cover carousel or hover preview

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk

anobaka and others added 30 commits March 24, 2026 14:12
- Add style tab in resource display settings with CSS variable sliders
- Support customizing cover border-radius, gap, and card padding
- Use left-right layout for compact slider controls
- Allow modifying resource filter operations in simple mode
- Fix font-size override on display property chips

https://claude.ai/code/session_012CHdopNPunYpK1pTbAJi4q
- Property-centric enhancer config with scenario-based grouping
- EnhancementConfigPanel with multi-select group/enhancer chips
- Per-property scope priority and property binding
- Dynamic target support with CoverSelectOrder config
- Regex enhancer: auto-sync capture groups, hide redundant DynamicTargets UI
- Fix pool=0 boundary issues: sanitize invalid PropertyPool/PropertyId at
  frontend load, submit, and display layers
- Allow modifying resource filter operations in simple mode

https://claude.ai/code/session_012AYwJu99Z2PQctNXM96UqV
…, file processor, and resource translation

resolve #998, resolve #999, resolve #1000, resolve #1001
…t toggles

- Replace single DisableCache toggle with DisableCoverCache and DisablePlayableFileCache
  in UIOptions, allowing users to independently control each cache type
- Update PrepareCacheTask to run when either cache type is enabled
- Update PrepareCache in ResourceService to skip disabled cache types
- Add RefreshResourceCache API endpoint (POST /cache/resource/{id}/refresh) that
  clears and rebuilds cache for a single resource, respecting cache toggles
- Update frontend settings UI with two separate checkboxes for cover and playable file cache
- Update ResourceCover to check disableCoverCache and PlayControl to check disablePlayableFileCache
- Add refresh cache button in resource list Operations (both aggregate and individual modes)
  and in resource DetailModal, shown only when resource has cached data
- Add localization keys for new cache toggles and refresh cache action (en/cn)

https://claude.ai/code/session_01CiDhFX2trWZAYkSg9YA3Vk
Add ability to validate enhancer configurations by selecting a resource
and running enhancement with the current (unsaved) settings. Users can
verify their enhancer setup before saving.

Backend:
- Add EnhanceResourceWithOptions to IEnhancerService for running
  enhancement with custom options
- Add POST /resource/{id}/enhancement/validate API endpoint

Frontend:
- Add EnhancerValidationModal with resource selector + validate flow
- Add "Validate Configuration" button to EnhancementConfigPanel footer
- Opens ResourceEnhancementsModal to display validation results
- Support repeated validation with result cleanup

https://claude.ai/code/session_01XtiMXv6Z4FSZV7jW5sXd6v
When reopening the EnhancementConfigPanel, instead of always defaulting
to the General group, auto-select groups that contain enhancers with
existing configuration. This prevents the confusing "no properties"
state when configured properties belong to non-General groups.

https://claude.ai/code/session_01XtiMXv6Z4FSZV7jW5sXd6v
Replace Windows-only WPF framework with cross-platform Avalonia UI:
- Replace WebView2 control with WebView.Avalonia for cross-platform web content
- Replace WinForms NotifyIcon with Avalonia TrayIcon
- Replace P/Invoke Win32 APIs (dark mode, icons, window focus) with Avalonia equivalents
- Replace WPF themes (Light.xaml/Dark.xaml) with Avalonia FluentTheme + ThemeVariant
- Convert all XAML from WPF syntax to Avalonia AXAML syntax
- Add Program.cs entry point (Avalonia requires explicit Main)
- Create AvaloniaGuiAdapter replacing WpfGuiAdapter
- Create CrossPlatformSystemService replacing WindowsSystemService
- Remove MissingWebView2Dialog (WebView.Avalonia bundles runtime)
- Remove WPF AssemblyInfo.cs (ThemeInfo attribute)
- Target net9.0 instead of net9.0-windows

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

fix: resolve compilation errors in Avalonia migration

- Add missing 'using Avalonia' in ErrorWindow.axaml.cs for Application type
- Rename TextBlock x:Name from "Title" to "ErrorTitle" to avoid conflict with Window.Title
- Fix ShowConfirmDialog: build dialog and buttons separately to avoid referencing 'dialog' before declaration
- Remove unnecessary async from ShowMainWebView (no await needed)
- Remove unused imports

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

fix: correct WebView assembly name in AXAML namespace

The WebView.Avalonia NuGet package produces assembly name 'Avalonia.WebView'
(from project file Avalonia.WebView.csproj), not 'WebView.Avalonia'.

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

fix: improve WebView error handling in ShowMainWebView

- Move MainWindow construction inside try block so AXAML parse errors
  are caught
- Null-safe close on error (window might not have been created)
- Include actual exception message in error dialog for debugging
- Reset _mainWindow to null on failure to avoid stale state

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

Replace WebView.Avalonia with NativeControlHost-based WebView

WebView.Avalonia 11.0.0.1 crashes on macOS + .NET 9 due to
AmbiguousMatchException in Builder.NativeImplementationBuilder's
ObjC interop layer. The package is effectively abandoned (repo disabled).

Replace with a custom NativeWebViewHost control using Avalonia's
NativeControlHost to embed platform-native WebView engines:
- macOS: WKWebView via direct objc_msgSend P/Invoke (bypasses broken ObjCRuntime)
- Windows: WebView2 via Microsoft.Web.WebView2.Core (reflection-loaded)
- Linux: WebKitGTK via P/Invoke to libwebkit2gtk

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

Fix dock icon, enable WKWebView dev tools, fix button padding

1. Dock icon: Set Window.Icon to /Assets/favicon.png in MainWindow.axaml
2. WKWebView dev tools: Enable developerExtrasEnabled on WKPreferences
   and setInspectable:YES (macOS 13.3+) for Safari Web Inspector debugging
3. Exit dialog buttons: Add Padding="0" to fix text rendering too low
   (Avalonia Fluent theme default Button padding is asymmetric: 11,5,11,6)
4. Add debug logging for Navigate URL to help diagnose blank page

To debug with Safari Web Inspector:
  Safari → Develop menu → pick the app → inspect the page

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

Add debug logging to CreateNativeControlCore

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

Set macOS Dock icon programmatically via NSApplication API

Non-bundled executables on macOS show generic "exec" icon. This uses
ObjC interop to load favicon.png and call setApplicationIconImage: on
NSApp. Also adds Info.plist and .icns for future .app bundle support.

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

Fix WKWebView height doubling on Retina displays

Remove autoresizingMask which conflicts with NativeControlHost's own
frame management, causing the height to be doubled on Retina displays.
Add explicit SizeChanged handler to manually sync WKWebView frame.

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

Improve dock icon and replace language Select with Dropdown

1. Dock icon: generate proper 1024x1024 icon with white squircle
   background and padded "B" to match macOS dock icon conventions.

2. Language selector: replace HeroUI Select with Dropdown for the nav
   bar. Trigger shows compact abbreviation ("中"/"EN"), dropdown menu
   shows full language names. Fixes truncated text in narrow sidebar.

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa

Increase language trigger button text size

Remove size="sm", add fontSize 16 and fontWeight 500 to match
surrounding icon buttons better.

https://claude.ai/code/session_01B73znyKBs3EQJnq3qH2GJa
- Replace custom OSS file-by-file updater with Velopack cross-platform auto-updates
- Remove legacy BakabaseUpdaterService and BakabaseUpdaterDiscover
- Update deploy.yml to upload Velopack releases and legacy paths for backward compatibility
  - New path: app/bakabase/releases/{rid}/ (Velopack)
  - Legacy installer zip: app/bakabase/inside-world/{version}/installer/{rid}/bakabase.zip
  - Legacy unpacked files: app/bakabase/inside-world/{version}/unpacked/win/ (for old auto-update)
- Make updater launch platform-aware with macOS quarantine handling
- Only request admin elevation when app directory requires it

https://claude.ai/code/session_01R44PgGtuYGC848pB3oEsbH
…tion

Implement multi-resource source architecture allowing resources to be linked
to multiple sources (Steam, DLsite, ExHentai, filesystem). Includes:

- ResourceSourceLink many-to-many relationship and conflict resolution
- Steam/DLsite/ExHentai API sync with multi-account support
- DLsite download/extract/play flow with DRM key support
- Resource discovery redesign using ResourceSourceLink for matching
- Playable system with multi-source icon priority
- User timezone configuration
- Avalonia cross-platform migration (WPF → Avalonia + WebView)
- AI/LLM integration with provider configuration and AI enhancer
- Enhancer configuration validation
- Split cache into cover and playable file caches
- UI style configuration with CSS variable overwrites
- Search index and property system improvements

https://claude.ai/code/session_01GkFjexwniREu9StGqE9yTY
… and update translations

- Add V230Migrator to convert legacy PlayableFilePaths (ListString) to PlayableItems (JSON) in resource cache for records missing PlayableItems data
- Mark PlayableFilePaths as [Obsolete] in both domain and DB models, scheduled for removal in v2.4
- Change menu translation for resource profile from "资源档案" to "资源配置"

https://claude.ai/code/session_01Qs2n3zcK1hZTfgYE82zrbD
…layable items, add external source features

- Remove DbValueType/BizValueType from Resource.Property constructor,
  keep as computed getters derived from PropertyType via PropertyTypeValueTypes
- Simplify FileName/Directory as computed getters from Path,
  remove RebuildPath and backing fields, add SetPath extension method
- Promote Covers/PlayableItems to first-class Resource fields with
  priority-based selection, add CoversReady/PlayableItemsReady status fields,
  rename HasMorePlayableFiles to HasMoreFileSystemPlayableItems
- Add CoverUrls/LocalCoverPaths to ResourceSourceLink for external
  cover localization, create DownloadExternalCoversTask BTask
- Add sync confirmation modal with redownloadCover option to
  Steam/DLsite/ExHentai pages with i18n support
- Create SourceMetadataMapping model and ISourceMetadataSyncService
  interface for auto-syncing external source metadata to resource properties
- Remove Steam Enhancer (replaced by source metadata sync),
  mark EnhancerId.Steam as obsolete

https://claude.ai/code/session_01JfhdSkGJLjsqv5VzRK8FA8
…ead of file path

The icon is embedded as AvaloniaResource, so it must be loaded via
AssetLoader.Open with avares:// URI, not from a filesystem path.

https://claude.ai/code/session_01JfhdSkGJLjsqv5VzRK8FA8
- Remove ShowTray/HideTray/SetTrayText/SetTrayIcon from IGuiAdapter
  (requires corresponding Bakabase.Infrastructures patch)
- Add ITrayIconController interface in Abstractions for tray icon switching
- AvaloniaGuiAdapter: manages tray natively with Avalonia resources,
  implements ITrayIconController for icon switching (favicon/tray-running)
- App.axaml.cs: creates tray on startup, wires exit to Host.TryToExit
- BTaskEventHandler: uses ITrayIconController instead of IGuiAdapter
- Remove System.Drawing.Icon dependency from tray code

https://claude.ai/code/session_01JfhdSkGJLjsqv5VzRK8FA8
Patch is based on Bakabase.Infrastructures dev/v2.3 branch.
Apply with: git apply 0001-Remove-tray-methods-from-IGuiAdapter-expose-TryToExi.patch

https://claude.ai/code/session_01JfhdSkGJLjsqv5VzRK8FA8
- App.axaml: declare TrayIcon with menu items (Open/Exit) in XAML
- App.axaml.cs: resolve XAML tray icon, wire events after Host creation
- AvaloniaGuiAdapter: remove ShowTray/HideTray, keep only SetTrayIcon
  which updates the XAML-declared icon via App.AppTrayIcon

https://claude.ai/code/session_01JfhdSkGJLjsqv5VzRK8FA8
The WebView2 NativeControlHost requires a manifest declaring supported
OS versions, otherwise Win32NativeControlHost fails to create a child
window. Adds app.manifest with Windows 7–11 support declarations.

https://claude.ai/code/session_01JfhdSkGJLjsqv5VzRK8FA8
These types don't have a Name property; resolve by index/header in code-behind instead.

https://claude.ai/code/session_01JfhdSkGJLjsqv5VzRK8FA8
CoreWebView2Environment.CreateAsync has no parameterless overload;
the correct signature is CreateAsync(string?, string?,
CoreWebView2EnvironmentOptions?) with all-null arguments.

https://claude.ai/code/session_01JfhdSkGJLjsqv5VzRK8FA8
…erV2

- Delete CompressedFileHelper.cs (was already marked [Obsolete])
- Move FromSingleFile<T> to standalone CompressedFileGroup class
- Update IwFsCompressedFileGroup to inherit from standalone CompressedFileGroup
- Update FileController.DecompressFiles to use CompressedFileHelperV2
- Remove dead commented-out code block in FileController
- Delete redundant CompressedFileHelperTests (V2 tests already cover this)

https://claude.ai/code/session_01SQbkENY9SGRnD1ztPQ3hUA
claude and others added 28 commits March 25, 2026 09:50
Temporarily shows a red badge with the source value on FileSystem
resources to verify positioning and diagnose why non-FileSystem
source icons are not appearing.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Steam icon (FaSteam) is an SVG that inherits text color from parent,
so brightness-0/invert filter is not needed. Apply img filter only
to DLsite/ExHentai PNG icons via descendant selector.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
- Move SourceLinks loading from optional ResourceAdditionalItem to
  mandatory population in ToDomainModel, so source icons always have
  the data they need
- Update frontend Resource model: replace single source/sourceKey
  with sourceLinks array matching the backend domain model
- Support multiple non-FileSystem source icons on resource covers

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Changes tooltip from just the source name (e.g., "Steam") to a more
descriptive "作为Steam资源启动" / "Launch as Steam resource" when
playable items for that source are loaded.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Resolvers now provide cover URLs during discovery:
- Steam: uses CDN header image URL
- DLsite: uses CoverUrl from cached work data
- ExHentai: uses CoverUrl from cached gallery data

ResourceSyncService passes CoverUrls through to ResourceSourceLink
for both new and existing resources. The existing
DownloadExternalCoversTask will then download them to local paths.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
EnsureLinks was only accepting (Source, SourceKey) tuples, discarding
CoverUrls entirely. Changed to accept full ResourceSourceLink objects
so CoverUrls are preserved for both new and existing links.

- Updated IResourceSourceLinkService.EnsureLinks signature
- Updated implementation to update CoverUrls on existing links
  when not already set
- Updated both callers in ResourceService

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Replace the narrow "download external covers" task with a general
"fetch external metadata" system that:

1. **SourceMetadataSyncService** - New service implementing
   ISourceMetadataSyncService with:
   - CRUD for SourceMetadataMapping (field → property bindings)
   - Available metadata fields per source (Steam, DLsite, ExHentai)
   - Metadata extraction from stored MetadataJson
   - Property value writing using PropertyValueScope per source

2. **FetchExternalMetadataTask** - Replaces DownloadExternalCoversTask:
   - Fetches detailed metadata from third-party APIs for items
     missing MetadataJson (Steam AppDetails, DLsite WorkDetail,
     ExHentai gallery detail)
   - Downloads covers (preserved from old task)
   - Applies SourceMetadataMappings to create property values

3. **Controller changes** - Rename redownloadCover → refetchMetadata:
   - When enabled, clears MetadataJson + MetadataFetchedAt +
     LocalCoverPaths, triggering full re-fetch on next task run

4. **Frontend** - MetadataMappingConfig component:
   - Shows available metadata fields with property selector
   - Re-apply mappings button for manual re-application
   - Integrated into Steam, DLsite, ExHentai config modals
   - Sync confirm checkbox updated to "refetch metadata"

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Steam: Added Type, DetailedDescription, CapsuleImage fields
DLsite: Added PropertiesOnTheRightSideOfCover as ListTag
  (key=group, value=tag - e.g. 声優/ジャンル etc.)
ExHentai: Added CoverUrl, FileCount, PageCount fields

Also added null-safe value construction helpers to reduce
boilerplate in extraction methods.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Instead of hardcoding available fields per source, users now manually
input metadata field paths. The extraction logic uses generic JSON
path navigation (dot-separated, case-insensitive) to read values
from MetadataJson.

Value type is auto-inferred from the JSON structure:
- String → String
- Number → Decimal
- Boolean → Boolean
- Array of strings → ListString
- Array of objects (with description/name) → ListString
- Object with string[] values → ListTag (key=group, value=tag)

Frontend MetadataMappingConfig now shows:
- Existing mappings with editable field path + property selector
- Input to add new field path → property mapping
- No predefined field dropdown

Removed: SourceMetadataFieldInfo model, GetAvailableMetadataFields API

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
…ields

Architecture changes:
- IResourceResolver now has GetPredefinedMetadataFields() and
  FetchDetailedMetadataAsync() with default implementations
- Each resolver (Steam, DLsite, ExHentai) implements both methods:
  - Predefined fields define the fixed metadata fields the source provides
  - FetchDetailedMetadataAsync calls the third-party client and returns
    predefined values + dynamic custom fields (Dict<string, List<string>>)
- FetchExternalMetadataTask uses resolver instead of calling clients directly
- SourceMetadataSyncService keeps generic JSON path extraction for applying
  mappings (works for both predefined and custom field paths)
- Controller exposes GET predefined-fields endpoint via resolver
- Fixed ReservedPropertyValue namespace ambiguity

Frontend MetadataMappingConfig now shows:
- Top section: predefined fields (always visible, highlighted)
- Bottom section: user-added custom fields
- Input to add new custom field path
- Each field can optionally be mapped to a target property

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
- Created SteamMetadataField, DLsiteMetadataField, ExHentaiMetadataField
  enums in ResourceResolver module
- Resolvers now use nameof(enum) for field names, ensuring consistency
  between backend field keys and frontend translation keys
- Added CN/EN translations for all predefined metadata fields:
  - Steam: 12 fields (名称/Name, 开发商/Developers, 类型标签/Genres, etc.)
  - DLsite: 4 fields (名称/Name, 简介/Introduction, 评分/Rating, 封面图片/Cover Images)
  - ExHentai: 8 fields (英文标题/English Title, 原始标题/Original Title, etc.)
- MetadataMappingConfig shows translated names for predefined fields
  with original field name as tooltip, custom fields show raw path

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
…rdParty

Resolves build errors caused by Bakabase.Modules.ResourceResolver not
having a reference to Bakabase.Modules.ThirdParty (for client classes).

Moved to Bakabase.Abstractions:
- IResourceResolver → Bakabase.Abstractions.Services
- Models (ResolvedResource, MigrationCandidate, etc.) → Bakabase.Abstractions.Models.Domain

Moved to Bakabase.Modules.ThirdParty/Resolvers:
- SteamResolver, DLsiteResolver, ExHentaiResolver
- SteamMetadataField, DLsiteMetadataField, ExHentaiMetadataField enums

Kept in Bakabase.Modules.ResourceResolver:
- FileSystemResolver (no ThirdParty dependency)
- ServiceCollectionExtensions (assembly-scanning DI registration)

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
…tions

- FileSystemResolver + DI registration → Bakabase.InsideWorld.Business/Components/ResourceResolver/
- Steam resolver + enum → ThirdParties/Steam/
- DLsite resolver + enum → ThirdParties/DLsite/
- ExHentai resolver + enum → ThirdParties/ExHentai/
- Removed Bakabase.Modules.ResourceResolver.csproj and solution entry
- Removed project reference from Business.csproj

Each resolver now lives alongside its corresponding ThirdParty client,
eliminating the cross-project dependency issue.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
…mespace conflict

Business project doesn't have ImplicitUsings enabled, so explicit
System.* usings are needed. Also added Resource type alias to resolve
conflict with Bakabase.InsideWorld.Business.Components.Resource namespace.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
The namespace Bakabase.InsideWorld.Business.Components.ResourceResolver
caused 'Resource' to resolve as the existing Components.Resource
namespace instead of the domain model type. Renamed to
Components.Resolvers to avoid the ambiguity.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
C# resolves 'Resource' as the existing Business.Components.Resource
namespace before checking type aliases. Using 'DomainResource' alias
instead to disambiguate the three method signatures that use the
domain Resource type.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
- Created MetadataMappingModal as a proper Modal component
- Removed MetadataMappingConfig from source config modals
  (Steam/DLsite/ExHentai Config no longer embed it)
- Deleted old MetadataMappingConfig.tsx
- Added "Metadata Sync Settings" button on each source list page
  (steam-apps, dlsite-works, exhentai-galleries) before the
  Configure button
- Button opens MetadataMappingModal with the correct ResourceSource

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
The filter chips were using t("Reserved") instead of
t("PropertyPool.Reserved"), so translations were not applied.
Added "PropertyPool." prefix to match the existing i18n keys.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
- Added description field to AccountField interface for rendering
  extra content below input fields
- Steam API Key field now shows an external link to
  https://steamcommunity.com/dev/apikey for obtaining the key

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Each source now has a single config modal with horizontal tabs:

Steam:
  - Accounts (API Key with help link, Steam ID)
  - Metadata Sync

DLsite:
  - Accounts (Cookie with validation)
  - Local Files (download dir, delete archive toggle, scan folders)
  - Metadata Sync
  - Locale Emulator (install/status)

ExHentai:
  - Accounts (Cookie)
  - Metadata Sync

Architecture:
- AccountsPanel: extracted reusable account management (non-modal)
- MetadataMappingPanel: extracted metadata mapping UI (non-modal)
- Each XxxConfig.tsx is now a self-contained 5xl Modal with Tabs
- Removed MetadataMappingModal (standalone modal no longer needed)
- Removed "Metadata Sync Settings" buttons from source list pages
- Single "Configure" button now opens the unified config

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
- Changed ExternalLink from Button to Link component
- Kept BApi.gui.openUrlInDefaultBrowser for opening URLs (webview)
- Updated SteamConfig to use ExternalLink for API key link
- Changed all source config modal tabs to vertical layout (isVertical)

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
1. Remove tab variant (was 'underlined', now default)
2. Fix tab content width: add classNames={{ panel: "flex-1 w-0" }}
   so tab content fills remaining width instead of minimal size
3. Fix property display showing pool:id instead of name:
   MetadataMappingPanel now loads all properties (Reserved + Custom)
   on init and builds a lookup map for existing mappings
4. Fix modal backdrop staying after close: use onOpenChange instead
   of onClose to properly handle HeroUI modal lifecycle

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
HeroUI controlled Modal leaves DOM elements and backdrop when
isOpen becomes false. Fix by conditionally rendering the entire
component: {configOpen && <XxxConfig isOpen onClose={...} />}
This ensures the Modal DOM is fully removed on close.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Switched from controlled isOpen/onClose rendering to
createPortal(XxxConfig, {}) pattern from BakabaseContext.

Config modals now:
- Use defaultOpen instead of controlled isOpen
- Use onClose → onDestroyed to let portal system handle cleanup
- Have proper close animation since HeroUI manages its own state
- No leftover backdrop/DOM since portal destroys the component

Source pages no longer need configOpen state or inline rendering.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
Instead of showing a different "set download dir" button with warning
color, simply disable the "open download dir" button when no download
directory is configured.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
LE install/status is now in the DLsite config modal's
Locale Emulator tab, no longer needed in the page header.

https://claude.ai/code/session_01CMrPS6kbEmGRtWY78nM6jk
@anobaka anobaka closed this Mar 26, 2026
@anobaka anobaka deleted the claude/add-source-icons-S19RG branch March 26, 2026 03:48
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.

2 participants