Save bookmark images

This commit is contained in:
Koitharu
2025-05-11 15:16:49 +03:00
parent 1bbe1204e6
commit 4ec9a91644
8 changed files with 80 additions and 6 deletions

View File

@@ -39,6 +39,7 @@ import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
import org.koitharu.kotatsu.list.ui.model.ListHeader
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.reader.ui.PageSaveHelper
import javax.inject.Inject
@AndroidEntryPoint
@@ -52,10 +53,19 @@ class AllBookmarksFragment :
@Inject
lateinit var settings: AppSettings
@Inject
lateinit var pageSaveHelperFactory: PageSaveHelper.Factory
private lateinit var pageSaveHelper: PageSaveHelper
private val viewModel by viewModels<AllBookmarksViewModel>()
private var bookmarksAdapter: BookmarksAdapter? = null
private var selectionController: ListSelectionController? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
pageSaveHelper = pageSaveHelperFactory.create(this)
}
override fun onCreateViewBinding(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -179,6 +189,12 @@ class AllBookmarksFragment :
true
}
R.id.action_save -> {
viewModel.savePages(pageSaveHelper, selectionController?.snapshot() ?: return false)
mode?.finish()
true
}
else -> false
}
}

View File

@@ -22,6 +22,7 @@ import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.LoadingState
import org.koitharu.kotatsu.list.ui.model.toErrorState
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.reader.ui.PageSaveHelper
import javax.inject.Inject
@HiltViewModel
@@ -56,6 +57,23 @@ class AllBookmarksViewModel @Inject constructor(
}
}
fun savePages(pageSaveHelper: PageSaveHelper, ids: Set<Long>) {
launchLoadingJob(Dispatchers.Default) {
val tasks = content.value.mapNotNull {
if (it !is Bookmark || it.pageId !in ids) return@mapNotNull null
PageSaveHelper.Task(
manga = it.manga,
chapterId = it.chapterId,
pageNumber = it.page + 1,
page = it.toMangaPage(),
)
}
val dest = pageSaveHelper.save(tasks)
val msg = if (dest.size == 1) R.string.page_saved else R.string.pages_saved
onActionDone.call(ReversibleAction(msg, null))
}
}
private fun mapList(data: Map<Manga, List<Bookmark>>): List<ListModel> {
val result = ArrayList<ListModel>(data.values.sumOf { it.size + 1 })
for ((manga, bookmarks) in data) {

View File

@@ -39,6 +39,7 @@ import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesViewModel
import org.koitharu.kotatsu.list.ui.GridSpanResolver
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
import org.koitharu.kotatsu.reader.ui.PageSaveHelper
import org.koitharu.kotatsu.reader.ui.ReaderNavigationCallback
import javax.inject.Inject
@@ -54,9 +55,13 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
@Inject
lateinit var settings: AppSettings
@Inject
lateinit var pageSaveHelperFactory: PageSaveHelper.Factory
override val recyclerView: RecyclerView?
get() = viewBinding?.recyclerView
private lateinit var pageSaveHelper: PageSaveHelper
private var bookmarksAdapter: BookmarksAdapter? = null
private var spanResolver: GridSpanResolver? = null
private var selectionController: ListSelectionController? = null
@@ -68,6 +73,7 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
pageSaveHelper = pageSaveHelperFactory.create(this)
activityViewModel.mangaDetails.observe(this, viewModel)
}
@@ -180,6 +186,12 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
true
}
R.id.action_save -> {
viewModel.savePages(pageSaveHelper, selectionController?.snapshot() ?: return false)
mode?.finish()
true
}
else -> false
}
}

View File

@@ -21,12 +21,14 @@ import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.ui.util.ReversibleAction
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
import org.koitharu.kotatsu.core.util.ext.call
import org.koitharu.kotatsu.core.util.ext.requireValue
import org.koitharu.kotatsu.details.data.MangaDetails
import org.koitharu.kotatsu.list.ui.model.EmptyState
import org.koitharu.kotatsu.list.ui.model.ListHeader
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.LoadingState
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.reader.ui.PageSaveHelper
import javax.inject.Inject
@HiltViewModel
@@ -62,6 +64,24 @@ class BookmarksViewModel @Inject constructor(
}
}
fun savePages(pageSaveHelper: PageSaveHelper, ids: Set<Long>) {
launchLoadingJob(Dispatchers.Default) {
val m = manga.requireValue()
val tasks = content.value.mapNotNull {
if (it !is Bookmark || it.pageId !in ids) return@mapNotNull null
PageSaveHelper.Task(
manga = m,
chapterId = it.chapterId,
pageNumber = it.page + 1,
page = it.toMangaPage(),
)
}
val dest = pageSaveHelper.save(tasks)
val msg = if (dest.size == 1) R.string.page_saved else R.string.pages_saved
onActionDone.call(ReversibleAction(msg, null))
}
}
private fun mapList(manga: Manga, bookmarks: List<Bookmark>): List<ListModel>? {
val chapters = manga.chapters ?: return null
val bookmarksMap = bookmarks.groupBy { it.chapterId }

View File

@@ -89,7 +89,7 @@ class PagesViewModel @Inject constructor(
val tasks = pages.map {
PageSaveHelper.Task(
manga = manga,
chapter = manga.requireChapterById(it.chapterId),
chapterId = it.chapterId,
pageNumber = it.index + 1,
page = it.toMangaPage(),
)

View File

@@ -178,15 +178,17 @@ class PageSaveHelper @AssistedInject constructor(
data class Task(
val manga: Manga,
val chapter: MangaChapter,
val chapterId: Long,
val pageNumber: Int,
val page: MangaPage,
) {
fun getFileBaseName() = buildString {
append(manga.title.toFileNameSafe().take(MAX_BASENAME_LENGTH))
append('-')
append(chapter.number)
manga.findChapterById(chapterId)?.let { chapter ->
append('-')
append(chapter.number)
}
append('-')
append(pageNumber)
append('_')

View File

@@ -257,7 +257,7 @@ class ReaderViewModel @Inject constructor(
val currentManga = manga.requireValue()
val task = PageSaveHelper.Task(
manga = currentManga,
chapter = currentManga.requireChapterById(state.chapterId),
chapterId = state.chapterId,
pageNumber = state.page + 1,
page = checkNotNull(getCurrentPage()) { "Cannot find current page" },
)

View File

@@ -9,4 +9,10 @@
android:title="@string/remove"
app:showAsAction="ifRoom|withText" />
</menu>
<item
android:id="@+id/action_save"
android:icon="@drawable/ic_save"
android:title="@string/save"
app:showAsAction="ifRoom|withText" />
</menu>