@@ -93,28 +93,55 @@ export function renderSkinStore(
9393 config : DashboardConfigRecord ,
9494 language : Language ,
9595) : string {
96- if ( ! state . open ) return ' ';
96+ const displayStyle = state . open ? 'display:flex' : 'display:none ';
9797
98- let content : string ;
98+ if ( ! state . open ) {
99+ return `
100+ <div class="nav-overlay" data-store-overlay style="${ displayStyle } ">
101+ <div class="nav-dialog" style="max-width:1200px;width:95vw">
102+ <h3>${ t ( language , 'editorSkinStore' ) } </h3>
103+ <div data-store-body></div>
104+ </div>
105+ </div>` ;
106+ }
107+
108+ return `
109+ <div class="nav-overlay" data-store-overlay style="${ displayStyle } ">
110+ <div class="nav-dialog" style="max-width:1200px;width:95vw">
111+ <h3>${ t ( language , 'editorSkinStore' ) } <span class="store-dependency" style="font-size:0.7em;font-weight:400;color:var(--sp-text-muted,#888)">${ linkifyDep ( t ( language , 'editorSkinStoreDependency' ) , language ) } </span></h3>
112+ <div data-store-body>
113+ ${ renderSkinStoreBody ( state , config , language ) }
114+ </div>
115+ </div>
116+ </div>
117+ ` ;
118+ }
119+
120+ export function renderSkinStoreBody (
121+ state : SkinStoreState ,
122+ config : DashboardConfigRecord ,
123+ language : Language ,
124+ ) : string {
99125 if ( state . loading ) {
100- content = `<p style="text-align:center;padding:40px 0;color:var(--sp-text-muted,#888)">${ t ( language , 'loadingQuote' ) } </p>` ;
101- } else if ( state . error ) {
102- content = `<p style="text-align:center;padding:40px 0;color:var(--sp-error,#e44)">${ t ( language , 'editorSkinStoreLoadFailed' ) } </p>` ;
103- } else {
104- const downloaded : string [ ] = config . downloaded_skins || [ ] ;
105- const filtered = filterThemes ( state . themes , state . searchQuery ) ;
106- const displayedCount = state . displayedCount || BATCH_SIZE ;
107- const visible = filtered . slice ( 0 , displayedCount ) ;
126+ return `<p style="text-align:center;padding:40px 0;color:var(--sp-text-muted,#888)">${ t ( language , 'loadingQuote' ) } </p>` ;
127+ }
128+ if ( state . error ) {
129+ return `<p style="text-align:center;padding:40px 0;color:var(--sp-error,#e44)">${ t ( language , 'editorSkinStoreLoadFailed' ) } </p>` ;
130+ }
131+ const downloaded : string [ ] = config . downloaded_skins || [ ] ;
132+ const filtered = filterThemes ( state . themes , state . searchQuery ) ;
133+ const displayedCount = state . displayedCount || BATCH_SIZE ;
134+ const visible = filtered . slice ( 0 , displayedCount ) ;
108135
109- const cards = visible . map ( theme => {
110- const installed = downloaded . includes ( theme . id ) ;
111- const dlCount = theme . downloads ?? '-' ;
112- const likeCount = theme . likes ?? 0 ;
113- const likedClass = theme . userLiked ? ' liked' : '' ;
114- const tagsHtml = theme . tags ?. length
115- ? `<div class="store-tags">${ theme . tags . slice ( 0 , 4 ) . map ( tag => `<span class="store-tag">${ tag } </span>` ) . join ( '' ) } </div>`
116- : '' ;
117- return `
136+ const cards = visible . map ( theme => {
137+ const installed = downloaded . includes ( theme . id ) ;
138+ const dlCount = theme . downloads ?? '-' ;
139+ const likeCount = theme . likes ?? 0 ;
140+ const likedClass = theme . userLiked ? ' liked' : '' ;
141+ const tagsHtml = theme . tags ?. length
142+ ? `<div class="store-tags">${ theme . tags . slice ( 0 , 4 ) . map ( tag => `<span class="store-tag">${ tag } </span>` ) . join ( '' ) } </div>`
143+ : '' ;
144+ return `
118145 <div class="store-card ${ installed ? 'store-installed' : '' } " data-store-theme="${ theme . id } ">
119146 <img src="${ CDN_STORE } /${ theme . thumbnail } " alt="${ theme . name } " class="store-thumb" loading="lazy">
120147 <div class="store-info">
@@ -134,37 +161,27 @@ export function renderSkinStore(
134161 }
135162 </div>
136163 </div>` ;
137- } ) ;
164+ } ) ;
138165
139- const remaining = Math . max ( 0 , filtered . length - displayedCount ) ;
140- const loader = remaining > 0
141- ? `<div class="store-load-more" data-store-load-more style="text-align:center;padding:16px;color:var(--sp-accent,#78a8b8);cursor:pointer; font-size:var(--sp-font-xs,13px);border-top:1px solid var(--sp-border -muted,var(--divider-color,rgba(0,0,0,0.08)));margin-top:12px ">
142- ${ t ( language , 'showAll' ) } (${ remaining } ${ t ( language , 'devices' ) } )
143- </div>`
144- : '' ;
166+ const remaining = Math . max ( 0 , filtered . length - displayedCount ) ;
167+ const loader = remaining > 0
168+ ? `<div class="store-load-indicator" style="text-align:center;padding:12px; font-size:var(--sp-font-2xs,11px);color: var(--sp-text -muted,#888) ">
169+ ${ t ( language , 'showAll' ) } (${ remaining } )
170+ </div>`
171+ : '' ;
145172
146- const resultLabel = filtered . length > 0
147- ? `<div class="store-result-count" style="font-size:var(--sp-font-3xs,10px);color:var(--sp-text-muted,#888);margin-bottom:8px;padding:0 4px">${ displayedCount } / ${ filtered . length } </div>`
148- : '' ;
173+ const resultLabel = filtered . length > 0
174+ ? `<div class="store-result-count" style="font-size:var(--sp-font-3xs,10px);color:var(--sp-text-muted,#888);margin-bottom:8px;padding:0 4px">${ displayedCount } / ${ filtered . length } </div>`
175+ : '' ;
149176
150- content = `
177+ return `
151178 <input type="text" class="store-search" data-store-search placeholder="${ t ( language , 'editorSkinStoreSearch' ) } " value="${ state . searchQuery || '' } " style="width:100%;box-sizing:border-box;padding:10px 14px;border-radius:var(--sp-radius-pill,999px);border:1px solid var(--sp-border-muted,var(--divider-color,rgba(0,0,0,0.12)));background:var(--sp-device-bg,rgba(128,128,128,0.06));color:var(--sp-text-main,inherit);font:inherit;font-size:var(--sp-font-xs,14px);outline:none;margin-bottom:var(--sp-space-md,16px);">
152179 ${ resultLabel }
153- <div class="store-grid">${ cards } </div>
154- ${ loader } ` ;
155- }
156-
157- return `
158- <div class="nav-overlay" data-store-overlay style="display:flex">
159- <div class="nav-dialog" style="max-width:1200px;width:95vw">
160- <h3>${ t ( language , 'editorSkinStore' ) } <span class="store-dependency" style="font-size:0.7em;font-weight:400;color:var(--sp-text-muted,#888)">${ linkifyDep ( t ( language , 'editorSkinStoreDependency' ) , language ) } </span></h3>
161- ${ content }
162- <div class="nav-dialog-actions">
163- <button class="nav-cancel" data-store-close>${ t ( language , 'editorSkinStoreClose' ) } </button>
164- </div>
165- </div>
166- </div>
167- ` ;
180+ <div class="store-grid">${ cards . join ( '' ) } </div>
181+ ${ loader }
182+ <div class="nav-dialog-actions">
183+ <button class="nav-cancel" data-store-close>${ t ( language , 'editorSkinStoreClose' ) } </button>
184+ </div>` ;
168185}
169186
170187export async function fetchSkinThemes ( ) : Promise < SkinStoreTheme [ ] > {
0 commit comments