Allow for Export and Import of Custom Covers
On pause for a few weeks, got exams - 28/04/25
Back on it now - 10/10/25
Resolves #16
How does this work?
What do you mean how does this work?
EDIT: Uses the manga url as a unique key to backup and restore covers stores into a gz (cus the manga id can change) it also stores a protobuf inside the archive to link filenames to the urls
Can someone rerun build cus I don't want any more force pushes showing xD
A potential issue I see here is in case a manga url or source id (which should be part of backup. manga is unique by source and url) changes any old backup will have some redundancy
What are the chances tho that 2 manga have the same URL
EDIT: I guess most sources now don't out the full URL in the URL field so it is possible
Would you like me to add the sourceID to the protobuf too and use that while restoring?
Yes
I didn't bother retesting like I usually do with changes, but it a pretty minor change so fingers crossed
I didn't bother retesting like I usually do with changes, but it a pretty minor change so fingers crossed
That's how I ended up having to make three follow-up PRs to #1748...
Quick question, I did a backup and restore last night.. saved covers weren't restored. This looks like this would restore the saved covers from extensions. Does it also work with saved covers from local storage folders/custom images?
No, this does not backup up the covers for local source as it is not necessary. I would recommend that you familiarize yourself with the Local Source Directory Structure https://mihon.app/docs/guides/local-source/
When a custom cover is set for an entry from local source, it replaces the cover.jpeg in the entries folder, so as long as you copy your local manga over, or set the location as the same, the covers are already set even without a backup or restore
I'm thinking of switching the default name to a similar format to regular backups, lmk if I should
fun getFilename(): String {
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.ENGLISH).format(Date())
return "${BuildConfig.APPLICATION_ID}_$date.tachibk"
}
Also should we just use a custom extension or leave it as .gz
It must not be confusable for a backup, ideally the filename alone would make sure of that (since file extensions may not even be visible to the user, like on Windows by default).
I don't want users in support trying to restore their library with a covers export file.
I mean I don't mean .tachibk but something like .mhcovers idk im making stuff up now but I get your point. The current name is mihon_custom_covers.gz
I mean I don't mean .tachibk but something like .mhcovers idk im making stuff up now but I get your point. The current name is mihon_custom_covers.gz
I'd add a timestamp to that, otherwise having multiple ones will get messy quickly.
I mean I don't mean .tachibk but something like .mhcovers idk im making stuff up now but I get your point. The current name is mihon_custom_covers.gz
I don't think that's necessary. IIRC the reason behind tachibk was GDrive quietly extracting .proto.gz automatically, leaving people with a uncompressed protobuf file that Mihon isn't expecting and users couldn't read.
With a "covers.gz" backup at worse they'll end up with a folder with the image files if GDrive or whatever does its meddling, or a file that's universally recognized as an archive.
Proposed filename, lmk if this is okay
mihon_custom_covers_2025-10-10_11-05.gz
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.ENGLISH).format(Date())
val customCoverFileName = "${stringResource(MR.strings.app_name)}_custom_covers_$date.gz"
Is it just a default pre-fill that the user can change before saving? Otherwise should probably include the package name to avoid mixing up with forks
Yeah it is just the default prefilled names and users can type in whatever they want, we can always use the package name instead but I used the app name because I doubt many people are backing up their custom covers especially with different releases of the same fork so I used app name for simplicity