@@ -34,6 +34,24 @@ function formatMetadataValue(value) {
3434 return value ;
3535}
3636
37+ // Save custom game metadata
38+ async function saveCustomGameMetadata ( gameId , metadataUpdates ) {
39+ try {
40+ // Call the main process to save the custom metadata
41+ const result = await window . electronAPI . saveCustomGameMetadata ( gameId , metadataUpdates ) ;
42+ if ( result . success ) {
43+ console . log ( `Successfully saved custom metadata for game ${ gameId } ` ) ;
44+ return true ;
45+ } else {
46+ console . error ( `Failed to save custom metadata: ${ result . message } ` ) ;
47+ return false ;
48+ }
49+ } catch ( error ) {
50+ console . error ( 'Error saving custom metadata:' , error ) ;
51+ return false ;
52+ }
53+ }
54+
3755// Format date to a readable string
3856function formatDate ( dateString ) {
3957 const date = new Date ( dateString ) ;
@@ -135,12 +153,53 @@ async function initInstalledGamesTab() {
135153
136154 additionalDetails = `
137155 <div class="detail-row">
138- <span class="detail-label">Direct3D:</span>
139- <span class="detail-value">${ direct3dInfo } </span>
156+ <span class="detail-label">Direct3D:</span>` ;
157+
158+ // If Direct3D info is unknown or custom_d3d is true, show a dropdown selector
159+ if ( direct3dInfo === 'No info about Direct3D versions' || metadata . custom_d3d === true ) {
160+ additionalDetails += `
161+ <span class="detail-value custom-selector">
162+ <select class="direct3d-selector" data-game-id="${ game . appid } ">
163+ <option value="">Choose Direct3D version</option>
164+ <option value="Direct3D 8" ${ metadata . direct3dVersions === 'Direct3D 8' ? 'selected' : '' } >Direct3D 8</option>
165+ <option value="Direct3D 9" ${ metadata . direct3dVersions === 'Direct3D 9' ? 'selected' : '' } >Direct3D 9</option>
166+ <option value="Direct3D 10" ${ metadata . direct3dVersions === 'Direct3D 10' ? 'selected' : '' } >Direct3D 10</option>
167+ <option value="Direct3D 11" ${ metadata . direct3dVersions === 'Direct3D 11' ? 'selected' : '' } >Direct3D 11</option>
168+ </select>
169+ </span>` ;
170+ } else {
171+ additionalDetails += `
172+ <span class="detail-value">${ direct3dInfo } </span>` ;
173+ }
174+
175+ additionalDetails += `
140176 </div>
141177 <div class="detail-row">
142- <span class="detail-label">Windows exec:</span>
143- <span class="detail-value">${ executableInfo } </span>
178+ <span class="detail-label">Windows exec:</span>` ;
179+
180+ // If executable info is unknown or custom_exec is true, show a dropdown selector
181+ if ( executableInfo === 'No info about Windows executable' || metadata . custom_exec === true ) {
182+ const is32bit = metadata . executable32bit === 'true' ;
183+ const is64bit = metadata . executable64bit === 'true' ;
184+ let selectedValue = '' ;
185+
186+ if ( is32bit ) selectedValue = 'x32' ;
187+ else if ( is64bit ) selectedValue = 'x64' ;
188+
189+ additionalDetails += `
190+ <span class="detail-value custom-selector">
191+ <select class="executable-selector" data-game-id="${ game . appid } ">
192+ <option value="">Choose architecture</option>
193+ <option value="x32" ${ selectedValue === 'x32' ? 'selected' : '' } >32-bit</option>
194+ <option value="x64" ${ selectedValue === 'x64' ? 'selected' : '' } >64-bit</option>
195+ </select>
196+ </span>` ;
197+ } else {
198+ additionalDetails += `
199+ <span class="detail-value">${ executableInfo } </span>` ;
200+ }
201+
202+ additionalDetails += `
144203 </div>` ;
145204 }
146205
@@ -166,11 +225,15 @@ async function initInstalledGamesTab() {
166225 // Only show the button for non-Vulkan games
167226 let buttonHtml = '' ;
168227 if ( ! hasVulkan ) {
169- const buttonClass = hasCompleteInfo ? 'action-btn' : 'action-btn disabled' ;
228+ // Set the button as enabled if:
229+ // 1. We have complete info from PCGamingWiki OR
230+ // 2. We have both custom_d3d and custom_exec (user has selected both values)
231+ const hasCompletedCustomInfo = metadata . custom_d3d === true && metadata . custom_exec === true ;
232+ const buttonClass = hasCompleteInfo || hasCompletedCustomInfo ? 'action-btn' : 'action-btn disabled' ;
170233 const buttonText = dxvkStatus && dxvkStatus . patched ? 'Update DXVK' : 'Manage DXVK' ;
171234
172235 buttonHtml = '<div class="buttons-container">' ;
173- buttonHtml += `<button class="${ buttonClass } " data-game-id="${ game . appid } " ${ ! hasCompleteInfo ? 'disabled' : '' } >${ buttonText } </button>` ;
236+ buttonHtml += `<button class="${ buttonClass } " data-game-id="${ game . appid } " ${ ! hasCompleteInfo && ! hasCompletedCustomInfo ? 'disabled' : '' } >${ buttonText } </button>` ;
174237
175238 // Add restore button if game has DXVK installed (patched), regardless of backup status
176239 if ( dxvkStatus && dxvkStatus . patched ) {
@@ -198,6 +261,58 @@ async function initInstalledGamesTab() {
198261 } ) ;
199262 }
200263
264+ // Add event listeners to the dropdowns if they exist
265+ const direct3dSelector = gameCard . querySelector ( '.direct3d-selector' ) ;
266+ if ( direct3dSelector ) {
267+ direct3dSelector . addEventListener ( 'change' , async ( e ) => {
268+ const gameId = e . target . getAttribute ( 'data-game-id' ) ;
269+ const selectedDirect3D = e . target . value ;
270+
271+ if ( selectedDirect3D ) {
272+ console . log ( `Selected Direct3D version ${ selectedDirect3D } for game ${ gameId } ` ) ;
273+
274+ // Update the game metadata
275+ const metadataUpdates = {
276+ direct3dVersions : selectedDirect3D ,
277+ custom_d3d : true
278+ } ;
279+
280+ if ( await saveCustomGameMetadata ( gameId , metadataUpdates ) ) {
281+ // Reload the installed games tab to reflect changes
282+ await initInstalledGamesTab ( ) ;
283+ } else {
284+ alert ( 'Failed to save Direct3D information. Please try again.' ) ;
285+ }
286+ }
287+ } ) ;
288+ }
289+
290+ const executableSelector = gameCard . querySelector ( '.executable-selector' ) ;
291+ if ( executableSelector ) {
292+ executableSelector . addEventListener ( 'change' , async ( e ) => {
293+ const gameId = e . target . getAttribute ( 'data-game-id' ) ;
294+ const selectedExec = e . target . value ;
295+
296+ if ( selectedExec ) {
297+ console . log ( `Selected Windows executable architecture ${ selectedExec } for game ${ gameId } ` ) ;
298+
299+ // Update the game metadata
300+ const metadataUpdates = {
301+ executable32bit : selectedExec === 'x32' ? 'true' : 'false' ,
302+ executable64bit : selectedExec === 'x64' ? 'true' : 'false' ,
303+ custom_exec : true
304+ } ;
305+
306+ if ( await saveCustomGameMetadata ( gameId , metadataUpdates ) ) {
307+ // Reload the installed games tab to reflect changes
308+ await initInstalledGamesTab ( ) ;
309+ } else {
310+ alert ( 'Failed to save executable architecture information. Please try again.' ) ;
311+ }
312+ }
313+ } ) ;
314+ }
315+
201316 // Add event listener to restore button if it exists
202317 const restoreBtn = gameCard . querySelector ( '.restore-btn' ) ;
203318 if ( restoreBtn ) {
@@ -803,4 +918,4 @@ async function initDxvkGplasyncTab() {
803918 console . error ( 'Error getting DXVK-gplasync releases:' , error ) ;
804919 gplasyncContainer . innerHTML = `<p>Error loading DXVK-gplasync releases: ${ error . message } </p>` ;
805920 }
806- }
921+ }
0 commit comments