Skip to content

Conversation

@arielj
Copy link
Collaborator

@arielj arielj commented Jan 4, 2026

This PR adds the actions to export the categories to a JSON file and also the option to import a JSON file with categories information.

For now it exports the categories inside the Games/Heroic folder, so we can be sure Heroic flatpak will have write access to it.

The buttons are at the bottom of the Manage Categories modal:

Captura de pantalla 2026-01-03 a la(s) 11 40 42 p  m

Closes #3416


Use the following Checklist if you have changed something on the Backend or Frontend:

  • Tested the feature and it's working on a current and clean install.
  • Tested the main App features and they are still working on a current and clean install. (Login, Install, Play, Uninstall, Move games, etc.)
  • Created / Updated Tests (If necessary)
  • Created / Updated documentation (If necessary)

@arielj arielj requested review from a team, CommandMC, Etaash-mathamsetty, Nocccer, biliesilva, flavioislima and imLinguin and removed request for a team January 4, 2026 02:43
@arielj arielj added the pr:ready-for-review Feature-complete, ready for the grind! :P label Jan 4, 2026
Copy link
Member

@flavioislima flavioislima left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@CommandMC CommandMC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think having the buttons in the modal itself makes sense, since they offer functionality you don't need often. Tucking them somewhere into the settings, or at least making the buttons less prominent, would be ideal

@arielj
Copy link
Collaborator Author

arielj commented Jan 6, 2026

I don't think having the buttons in the modal itself makes sense, since they offer functionality you don't need often. Tucking them somewhere into the settings, or at least making the buttons less prominent, would be ideal

maybe I can hide the 2 buttons inside a <details> tag collapsed by default?

what I like about the buttons in the modal is that it makes it really easy to discover them, it's right next to where categories are managed

I think collapsing them and show them only on demand can help clean it up and keep them easily discoverable, I'll update the PR

@arielj
Copy link
Collaborator Author

arielj commented Jan 6, 2026

This is how it looks like now, collapsed by default

Captura de pantalla 2026-01-06 a la(s) 10 45 16 a  m Captura de pantalla 2026-01-06 a la(s) 10 45 22 a  m

Copy link
Member

@CommandMC CommandMC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for another nitpick, testing things now:

  • One button says "Export to file", the other "Import file". To keep them consistent, I'd either change the one to "Export file", or the other to "Import from file"
  • Maybe add icons to the buttons?

Comment on lines +19 to +29
const jsonContent = JSON.parse(content) as Record<string, string[]>

for (const key in jsonContent) {
// some checks to ensure we don't break the categories if the
// json file is not the correct format
// only allow string keys
if (typeof key !== 'string') continue

// only allow an array of strings
if (!Array.isArray(jsonContent[key])) continue
const gameIds = jsonContent[key].filter((val) => typeof val === 'string')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like an obvious use case for Zod

// Somewhere at the start of the file
const ImportSchema = z.record(z.string(), z.string().array())

// Inside the function
const jsonContent = JSON.parse(content)
const validatedContent = ImportSchema.parse(jsonContent)
// validatedContent is now of type Record<string, string[]>

If we truly want to accept partially-malformed category exports, we could still handle that in Zod with some transforms. IMO we should just not do that though, I don't think that's a common use case

Comment on lines +58 to +59
export const exportCategories = makeHandlerInvoker('exportCategories')
export const importCategories = makeHandlerInvoker('importCategories')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you seem to be looking to create more exporters/importers, you may want to create a "category" for those IPC functions. It makes them easier to find & lessens the load on the language server (well, it would if we had more of them)

A "category" is just an object with properties, like this example:

export const systemInfo = {
get: makeHandlerInvoker('getSystemInfo'),
copyToClipboard: makeListenerCaller('copySystemInfoToClipboard')
}

(whether you sort them export.categories or categories.export is up to you)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the idea is that we could have more importers/exporters for other things in the future, like the app settings for example that users currently have to copy around internal files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:ready-for-review Feature-complete, ready for the grind! :P

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exporting the categories to a file for backup purposes

4 participants