LibrarySettingsDialog.kt 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package eu.kanade.presentation.library
  2. import android.content.res.Configuration
  3. import androidx.compose.foundation.layout.Column
  4. import androidx.compose.foundation.layout.ColumnScope
  5. import androidx.compose.foundation.layout.padding
  6. import androidx.compose.foundation.rememberScrollState
  7. import androidx.compose.foundation.verticalScroll
  8. import androidx.compose.runtime.Composable
  9. import androidx.compose.runtime.getValue
  10. import androidx.compose.runtime.remember
  11. import androidx.compose.ui.Modifier
  12. import androidx.compose.ui.platform.LocalConfiguration
  13. import androidx.compose.ui.res.stringResource
  14. import eu.kanade.presentation.components.TabbedDialog
  15. import eu.kanade.presentation.components.TabbedDialogPaddings
  16. import eu.kanade.presentation.components.TriStateItem
  17. import eu.kanade.presentation.util.collectAsState
  18. import eu.kanade.tachiyomi.R
  19. import eu.kanade.tachiyomi.ui.library.LibrarySettingsScreenModel
  20. import tachiyomi.domain.category.model.Category
  21. import tachiyomi.domain.library.model.LibraryDisplayMode
  22. import tachiyomi.domain.library.model.LibrarySort
  23. import tachiyomi.domain.library.model.sort
  24. import tachiyomi.domain.library.service.LibraryPreferences
  25. import tachiyomi.domain.manga.model.TriStateFilter
  26. import tachiyomi.presentation.core.components.CheckboxItem
  27. import tachiyomi.presentation.core.components.HeadingItem
  28. import tachiyomi.presentation.core.components.RadioItem
  29. import tachiyomi.presentation.core.components.SliderItem
  30. import tachiyomi.presentation.core.components.SortItem
  31. @Composable
  32. fun LibrarySettingsDialog(
  33. onDismissRequest: () -> Unit,
  34. screenModel: LibrarySettingsScreenModel,
  35. category: Category?,
  36. ) {
  37. TabbedDialog(
  38. onDismissRequest = onDismissRequest,
  39. tabTitles = listOf(
  40. stringResource(R.string.action_filter),
  41. stringResource(R.string.action_sort),
  42. stringResource(R.string.action_display),
  43. ),
  44. ) { page ->
  45. Column(
  46. modifier = Modifier
  47. .padding(vertical = TabbedDialogPaddings.Vertical)
  48. .verticalScroll(rememberScrollState()),
  49. ) {
  50. when (page) {
  51. 0 -> FilterPage(
  52. screenModel = screenModel,
  53. )
  54. 1 -> SortPage(
  55. category = category,
  56. screenModel = screenModel,
  57. )
  58. 2 -> DisplayPage(
  59. screenModel = screenModel,
  60. )
  61. }
  62. }
  63. }
  64. }
  65. @Composable
  66. private fun ColumnScope.FilterPage(
  67. screenModel: LibrarySettingsScreenModel,
  68. ) {
  69. val filterDownloaded by screenModel.libraryPreferences.filterDownloaded().collectAsState()
  70. val downloadedOnly by screenModel.preferences.downloadedOnly().collectAsState()
  71. TriStateItem(
  72. label = stringResource(R.string.label_downloaded),
  73. state = if (downloadedOnly) {
  74. TriStateFilter.ENABLED_IS
  75. } else {
  76. filterDownloaded
  77. },
  78. enabled = !downloadedOnly,
  79. onClick = { screenModel.toggleFilter(LibraryPreferences::filterDownloaded) },
  80. )
  81. val filterUnread by screenModel.libraryPreferences.filterUnread().collectAsState()
  82. TriStateItem(
  83. label = stringResource(R.string.action_filter_unread),
  84. state = filterUnread,
  85. onClick = { screenModel.toggleFilter(LibraryPreferences::filterUnread) },
  86. )
  87. val filterStarted by screenModel.libraryPreferences.filterStarted().collectAsState()
  88. TriStateItem(
  89. label = stringResource(R.string.label_started),
  90. state = filterStarted,
  91. onClick = { screenModel.toggleFilter(LibraryPreferences::filterStarted) },
  92. )
  93. val filterBookmarked by screenModel.libraryPreferences.filterBookmarked().collectAsState()
  94. TriStateItem(
  95. label = stringResource(R.string.action_filter_bookmarked),
  96. state = filterBookmarked,
  97. onClick = { screenModel.toggleFilter(LibraryPreferences::filterBookmarked) },
  98. )
  99. val filterCompleted by screenModel.libraryPreferences.filterCompleted().collectAsState()
  100. TriStateItem(
  101. label = stringResource(R.string.completed),
  102. state = filterCompleted,
  103. onClick = { screenModel.toggleFilter(LibraryPreferences::filterCompleted) },
  104. )
  105. val trackServices = remember { screenModel.trackServices }
  106. when (trackServices.size) {
  107. 0 -> {
  108. // No trackers
  109. }
  110. 1 -> {
  111. val service = trackServices[0]
  112. val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
  113. TriStateItem(
  114. label = stringResource(R.string.action_filter_tracked),
  115. state = filterTracker,
  116. onClick = { screenModel.toggleTracker(service.id.toInt()) },
  117. )
  118. }
  119. else -> {
  120. HeadingItem(R.string.action_filter_tracked)
  121. trackServices.map { service ->
  122. val filterTracker by screenModel.libraryPreferences.filterTracking(service.id.toInt()).collectAsState()
  123. TriStateItem(
  124. label = stringResource(service.nameRes()),
  125. state = filterTracker,
  126. onClick = { screenModel.toggleTracker(service.id.toInt()) },
  127. )
  128. }
  129. }
  130. }
  131. }
  132. @Composable
  133. private fun ColumnScope.SortPage(
  134. category: Category?,
  135. screenModel: LibrarySettingsScreenModel,
  136. ) {
  137. val sortingMode = category.sort.type
  138. val sortDescending = !category.sort.isAscending
  139. listOf(
  140. R.string.action_sort_alpha to LibrarySort.Type.Alphabetical,
  141. R.string.action_sort_total to LibrarySort.Type.TotalChapters,
  142. R.string.action_sort_last_read to LibrarySort.Type.LastRead,
  143. R.string.action_sort_last_manga_update to LibrarySort.Type.LastUpdate,
  144. R.string.action_sort_unread_count to LibrarySort.Type.UnreadCount,
  145. R.string.action_sort_latest_chapter to LibrarySort.Type.LatestChapter,
  146. R.string.action_sort_chapter_fetch_date to LibrarySort.Type.ChapterFetchDate,
  147. R.string.action_sort_date_added to LibrarySort.Type.DateAdded,
  148. ).map { (titleRes, mode) ->
  149. SortItem(
  150. label = stringResource(titleRes),
  151. sortDescending = sortDescending.takeIf { sortingMode == mode },
  152. onClick = {
  153. val isTogglingDirection = sortingMode == mode
  154. val direction = when {
  155. isTogglingDirection -> if (sortDescending) LibrarySort.Direction.Ascending else LibrarySort.Direction.Descending
  156. else -> if (sortDescending) LibrarySort.Direction.Descending else LibrarySort.Direction.Ascending
  157. }
  158. screenModel.setSort(category, mode, direction)
  159. },
  160. )
  161. }
  162. }
  163. @Composable
  164. private fun ColumnScope.DisplayPage(
  165. screenModel: LibrarySettingsScreenModel,
  166. ) {
  167. HeadingItem(R.string.action_display_mode)
  168. val displayMode by screenModel.libraryPreferences.libraryDisplayMode().collectAsState()
  169. listOf(
  170. R.string.action_display_grid to LibraryDisplayMode.CompactGrid,
  171. R.string.action_display_comfortable_grid to LibraryDisplayMode.ComfortableGrid,
  172. R.string.action_display_cover_only_grid to LibraryDisplayMode.CoverOnlyGrid,
  173. R.string.action_display_list to LibraryDisplayMode.List,
  174. ).map { (titleRes, mode) ->
  175. RadioItem(
  176. label = stringResource(titleRes),
  177. selected = displayMode == mode,
  178. onClick = { screenModel.setDisplayMode(mode) },
  179. )
  180. }
  181. if (displayMode != LibraryDisplayMode.List) {
  182. val configuration = LocalConfiguration.current
  183. val columnPreference = remember {
  184. if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
  185. screenModel.libraryPreferences.landscapeColumns()
  186. } else {
  187. screenModel.libraryPreferences.portraitColumns()
  188. }
  189. }
  190. val columns by columnPreference.collectAsState()
  191. SliderItem(
  192. label = stringResource(R.string.pref_library_columns),
  193. max = 10,
  194. value = columns,
  195. valueText = if (columns > 0) {
  196. stringResource(R.string.pref_library_columns_per_row, columns)
  197. } else {
  198. stringResource(R.string.label_default)
  199. },
  200. onChange = { columnPreference.set(it) },
  201. )
  202. }
  203. HeadingItem(R.string.overlay_header)
  204. val downloadBadge by screenModel.libraryPreferences.downloadBadge().collectAsState()
  205. CheckboxItem(
  206. label = stringResource(R.string.action_display_download_badge),
  207. checked = downloadBadge,
  208. onClick = {
  209. screenModel.togglePreference(LibraryPreferences::downloadBadge)
  210. },
  211. )
  212. val localBadge by screenModel.libraryPreferences.localBadge().collectAsState()
  213. CheckboxItem(
  214. label = stringResource(R.string.action_display_local_badge),
  215. checked = localBadge,
  216. onClick = {
  217. screenModel.togglePreference(LibraryPreferences::localBadge)
  218. },
  219. )
  220. val languageBadge by screenModel.libraryPreferences.languageBadge().collectAsState()
  221. CheckboxItem(
  222. label = stringResource(R.string.action_display_language_badge),
  223. checked = languageBadge,
  224. onClick = {
  225. screenModel.togglePreference(LibraryPreferences::languageBadge)
  226. },
  227. )
  228. val showContinueReadingButton by screenModel.libraryPreferences.showContinueReadingButton().collectAsState()
  229. CheckboxItem(
  230. label = stringResource(R.string.action_display_show_continue_reading_button),
  231. checked = showContinueReadingButton,
  232. onClick = {
  233. screenModel.togglePreference(LibraryPreferences::showContinueReadingButton)
  234. },
  235. )
  236. HeadingItem(R.string.tabs_header)
  237. val categoryTabs by screenModel.libraryPreferences.categoryTabs().collectAsState()
  238. CheckboxItem(
  239. label = stringResource(R.string.action_display_show_tabs),
  240. checked = categoryTabs,
  241. onClick = {
  242. screenModel.togglePreference(LibraryPreferences::categoryTabs)
  243. },
  244. )
  245. val categoryNumberOfItems by screenModel.libraryPreferences.categoryNumberOfItems().collectAsState()
  246. CheckboxItem(
  247. label = stringResource(R.string.action_display_show_number_of_items),
  248. checked = categoryNumberOfItems,
  249. onClick = {
  250. screenModel.togglePreference(LibraryPreferences::categoryNumberOfItems)
  251. },
  252. )
  253. }