diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt
index 0bfa15438..ec97527eb 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt
@@ -282,4 +282,6 @@ object PreferenceKeys {
     const val webtoonEnableZoomOut = "webtoon_enable_zoom_out"
 
     const val startReadingButton = "start_reading_button"
+
+    const val groupLibraryBy = "group_library_by"
 }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
index c773a5876..bd33d5dd3 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
@@ -386,4 +386,6 @@ class PreferencesHelper(val context: Context) {
     fun webtoonEnableZoomOut() = flowPrefs.getBoolean(Keys.webtoonEnableZoomOut, false)
 
     fun startReadingButton() = flowPrefs.getBoolean(Keys.startReadingButton, true)
+
+    fun groupLibraryBy() = flowPrefs.getInt(Keys.groupLibraryBy, 0)
 }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt
index 1315cc660..5a3ff8420 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt
@@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.data.database.models.LibraryManga
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.Track
 import eu.kanade.tachiyomi.data.database.tables.MangaTable
+import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.ui.category.CategoryAdapter
@@ -44,6 +45,7 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC
     private var lastFilterJob: Job? = null
     private val sourceManager: SourceManager by injectLazy()
     private val trackManager: TrackManager by injectLazy()
+    private val preferences: PreferencesHelper by injectLazy()
     private val hasLoggedServices by lazy {
         trackManager.hasLoggedServices()
     }
@@ -86,7 +88,7 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC
         return currentItems.indexOfFirst { it.manga.id == manga.id }
     }
 
-    fun canDrag() = (mode != Mode.MULTI || (mode == Mode.MULTI && selectedItemCount == 1)) && searchText.isBlank()
+    fun canDrag() = (mode != Mode.MULTI || (mode == Mode.MULTI && selectedItemCount == 1)) && searchText.isBlank() && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT
 
     // EXH -->
     // Note that we cannot use FlexibleAdapter's built in filtering system as we cannot cancel it
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt
index 5ac09c5d6..63e84fe94 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt
@@ -213,7 +213,13 @@ class LibraryController(
                 is LibrarySettingsSheet.Sort.SortGroup -> onSortChanged()
                 is LibrarySettingsSheet.Display.DisplayGroup -> reattachAdapter()
                 is LibrarySettingsSheet.Display.BadgeGroup -> onBadgeSettingChanged()
+                // SY -->
+                is LibrarySettingsSheet.Display.ButtonsGroup -> onButtonSettingChanged()
+                // SY <--
                 is LibrarySettingsSheet.Display.TabsGroup -> onTabsSettingsChanged()
+                // SY -->
+                is LibrarySettingsSheet.Grouping.InternalGroup -> onGroupSettingChanged()
+                // SY <--
             }
         }
 
@@ -336,6 +342,16 @@ class LibraryController(
         presenter.requestBadgesUpdate()
     }
 
+    // SY -->
+    private fun onButtonSettingChanged() {
+        presenter.requestButtonsUpdate()
+    }
+
+    private fun onGroupSettingChanged() {
+        presenter.requestGroupsUpdate()
+    }
+    // SY <--
+
     private fun onTabsSettingsChanged() {
         tabsVisibilityRelay.call(preferences.categoryTabs().get() && adapter?.categories?.size ?: 0 > 1)
         updateTitle()
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGroup.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGroup.kt
new file mode 100644
index 000000000..64559c522
--- /dev/null
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGroup.kt
@@ -0,0 +1,32 @@
+package eu.kanade.tachiyomi.ui.library
+
+import eu.kanade.tachiyomi.R
+
+object LibraryGroup {
+
+    const val BY_DEFAULT = 0
+    const val BY_SOURCE = 1
+    const val BY_STATUS = 2
+    const val BY_TRACK_STATUS = 3
+    const val UNGROUPED = 4
+
+    fun groupTypeStringRes(type: Int, hasCategories: Boolean = true): Int {
+        return when (type) {
+            BY_STATUS -> R.string.status
+            BY_SOURCE -> R.string.label_sources
+            BY_TRACK_STATUS -> R.string.tracking_status
+            UNGROUPED -> R.string.ungrouped
+            else -> if (hasCategories) R.string.categories else R.string.ungrouped
+        }
+    }
+
+    fun groupTypeDrawableRes(type: Int): Int {
+        return when (type) {
+            BY_STATUS -> R.drawable.ic_progress_clock_24dp
+            BY_TRACK_STATUS -> R.drawable.ic_sync_24dp
+            BY_SOURCE -> R.drawable.ic_explore_24dp
+            UNGROUPED -> R.drawable.ic_ungroup_24dp
+            else -> R.drawable.ic_label_24dp
+        }
+    }
+}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
index 0c96e1258..8e139b55d 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.library
 
 import android.os.Bundle
 import com.jakewharton.rxrelay.BehaviorRelay
+import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Category
@@ -11,6 +12,7 @@ import eu.kanade.tachiyomi.data.database.models.MangaCategory
 import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.data.library.CustomMangaManager
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.source.model.Filter.TriState.Companion.STATE_EXCLUDE
 import eu.kanade.tachiyomi.source.model.Filter.TriState.Companion.STATE_IGNORE
@@ -89,9 +91,26 @@ class LibraryPresenter(
      */
     private var librarySubscription: Subscription? = null
 
-    // --> EXH
+    // SY -->
     val favoritesSync = FavoritesSyncHelper(context)
-    // <-- EXH
+
+    private var groupType = preferences.groupLibraryBy().get()
+
+    private val libraryIsGrouped
+        get() = groupType != LibraryGroup.UNGROUPED
+
+    private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLogged } }
+
+    /**
+     * Relay used to apply the UI update to the last emission of the library.
+     */
+    private val buttonTriggerRelay = BehaviorRelay.create(Unit)
+
+    /**
+     * Relay used to apply the UI update to the last emission of the library.
+     */
+    private val groupingTriggerRelay = BehaviorRelay.create(Unit)
+    // SY <--
 
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
@@ -107,6 +126,15 @@ class LibraryPresenter(
                 .combineLatest(badgeTriggerRelay.observeOn(Schedulers.io())) { lib, _ ->
                     lib.apply { setBadges(mangaMap) }
                 }
+                // SY -->
+                .combineLatest(buttonTriggerRelay.observeOn(Schedulers.io())) { lib, _ ->
+                    lib.apply { setButtons(mangaMap) }
+                }
+                .combineLatest(groupingTriggerRelay.observeOn(Schedulers.io())) { lib, _ ->
+                    val (map, categories) = applyGrouping(lib.mangaMap, lib.categories)
+                    lib.copy(mangaMap = map, categories = categories)
+                }
+                // SY <--
                 .combineLatest(filterTriggerRelay.observeOn(Schedulers.io())) { lib, _ ->
                     lib.copy(mangaMap = applyFilters(lib.mangaMap))
                 }
@@ -172,6 +200,21 @@ class LibraryPresenter(
 
         return map.mapValues { entry -> entry.value.filter(filterFn) }
     }
+
+    /**
+     * Sets the button on each manga.
+     *
+     * @param map the map of manga.
+     */
+    private fun setButtons(map: LibraryMap) {
+        val startReadingButton = preferences.startReadingButton().get()
+
+        for ((_, itemList) in map) {
+            for (item in itemList) {
+                item.startReadingButton = startReadingButton
+            }
+        }
+    }
     // SY <--
 
     /**
@@ -182,7 +225,6 @@ class LibraryPresenter(
     private fun setBadges(map: LibraryMap) {
         val showDownloadBadges = preferences.downloadBadge().get()
         val showUnreadBadges = preferences.unreadBadge().get()
-        val startReadingButton = preferences.startReadingButton().get()
 
         for ((_, itemList) in map) {
             for (item in itemList) {
@@ -199,10 +241,6 @@ class LibraryPresenter(
                     // Unset unread count if not enabled
                     -1
                 }
-
-                // SY -->
-                item.startReadingButton = startReadingButton
-                // SY <--
             }
         }
     }
@@ -294,6 +332,27 @@ class LibraryPresenter(
         }
     }
 
+    // SY -->
+    private fun applyGrouping(map: LibraryMap, categories: List<Category>): Pair<LibraryMap, List<Category>> {
+        groupType = preferences.groupLibraryBy().get()
+        var editedCategories: List<Category> = categories
+        val libraryMangaAsList = map.flatMap { it.value }.distinctBy { it.manga.id }
+        val items = if (groupType == LibraryGroup.BY_DEFAULT) {
+            map
+        } else if (!libraryIsGrouped) {
+            editedCategories = listOf(Category.create("All").apply { this.id = 0 })
+            libraryMangaAsList
+                .groupBy { 0 }
+        } else {
+            val (items, customCategories) = getGroupedMangaItems(libraryMangaAsList)
+            editedCategories = customCategories
+            items
+        }
+
+        return items to editedCategories
+    }
+    // SY <--
+
     /**
      * Get the categories from the database.
      *
@@ -331,6 +390,23 @@ class LibraryPresenter(
         badgeTriggerRelay.call(Unit)
     }
 
+    // SY -->
+    /**
+     * Requests the library to have buttons toggled.
+     */
+    fun requestButtonsUpdate() {
+        buttonTriggerRelay.call(Unit)
+    }
+
+    /**
+     * Requests the library to have groups refreshed.
+     */
+    fun requestGroupsUpdate() {
+        groupingTriggerRelay.call(Unit)
+    }
+
+    // SY <--
+
     /**
      * Requests the library to be sorted.
      */
@@ -491,5 +567,109 @@ class LibraryPresenter(
             chapters.sortedByDescending { it.source_order }.find { !it.read }
         }
     }
+
+    private fun getGroupedMangaItems(libraryManga: List<LibraryItem>): Pair<LibraryMap, List<Category>> {
+        val grouping: MutableList<Triple<String, Int, String>> = mutableListOf()
+        when (groupType) {
+            LibraryGroup.BY_STATUS -> libraryManga.distinctBy { it.manga.status }.map { it.manga.status }.forEachIndexed { index, status ->
+                grouping += Triple(status.toString(), index, mapStatus(status))
+            }
+            LibraryGroup.BY_SOURCE -> libraryManga.distinctBy { it.manga.source }.map { it.manga.source }.forEachIndexed { index, sourceLong ->
+                grouping += Triple(sourceLong.toString(), index, sourceManager.getOrStub(sourceLong).name)
+            }
+            LibraryGroup.BY_TRACK_STATUS -> {
+                grouping += Triple("1", 1, context.getString(R.string.reading))
+                grouping += Triple("2", 2, context.getString(R.string.repeating))
+                grouping += Triple("3", 3, context.getString(R.string.plan_to_read))
+                grouping += Triple("4", 4, context.getString(R.string.on_hold))
+                grouping += Triple("5", 5, context.getString(R.string.completed))
+                grouping += Triple("6", 6, context.getString(R.string.dropped))
+                grouping += Triple("7", 7, context.getString(R.string.not_tracked))
+            }
+        }
+        val map: MutableMap<Int, MutableList<LibraryItem>> = mutableMapOf()
+
+        libraryManga.forEach { libraryItem ->
+            when (groupType) {
+                LibraryGroup.BY_TRACK_STATUS -> {
+                    val status: String = {
+                        val tracks = db.getTracks(libraryItem.manga).executeAsBlocking()
+                        val track = tracks.find { track ->
+                            loggedServices.any { it.id == track?.sync_id }
+                        }
+                        val service = loggedServices.find { it.id == track?.sync_id }
+                        if (track != null && service != null) {
+                            service.getStatus(track.status)
+                        } else {
+                            "not tracked"
+                        }
+                    }()
+                    val group = grouping.find { it.first == mapTrackingOrder(status) }
+                    if (group != null) {
+                        map[group.second]?.plusAssign(libraryItem) ?: map.put(group.second, mutableListOf(libraryItem))
+                    } else {
+                        map[7]?.plusAssign(libraryItem) ?: map.put(7, mutableListOf(libraryItem))
+                    }
+                }
+                LibraryGroup.BY_SOURCE -> {
+                    val group = grouping.find { it.first.toLongOrNull() == libraryItem.manga.source }
+                    if (group != null) {
+                        map[group.second]?.plusAssign(libraryItem) ?: map.put(group.second, mutableListOf(libraryItem))
+                    } else {
+                        if (grouping.all { it.second != Int.MAX_VALUE }) grouping += Triple(Int.MAX_VALUE.toString(), Int.MAX_VALUE, context.getString(R.string.unknown))
+                        map[Int.MAX_VALUE]?.plusAssign(libraryItem) ?: map.put(Int.MAX_VALUE, mutableListOf(libraryItem))
+                    }
+                }
+                else -> {
+                    val group = grouping.find { it.first == libraryItem.manga.status.toString() }
+                    if (group != null) {
+                        map[group.second]?.plusAssign(libraryItem) ?: map.put(group.second, mutableListOf(libraryItem))
+                    } else {
+                        if (grouping.all { it.second != Int.MAX_VALUE }) grouping += Triple(Int.MAX_VALUE.toString(), Int.MAX_VALUE, context.getString(R.string.unknown))
+                        map[Int.MAX_VALUE]?.plusAssign(libraryItem) ?: map.put(Int.MAX_VALUE, mutableListOf(libraryItem))
+                    }
+                }
+            }
+        }
+
+        val categories = (
+            when (groupType) {
+                LibraryGroup.BY_SOURCE -> grouping.sortedBy { it.third.toLowerCase() }
+                LibraryGroup.BY_TRACK_STATUS -> grouping.filter { it.second in map.keys }
+                else -> grouping
+            }
+            ).map {
+            val category = Category.create(it.third)
+            category.id = it.second
+            category
+        }
+
+        return map to categories
+    }
+
+    private fun mapTrackingOrder(status: String): String {
+        with(context) {
+            return when (status) {
+                getString(R.string.reading), getString(R.string.currently_reading) -> "1"
+                getString(R.string.repeating) -> "2"
+                getString(R.string.plan_to_read), getString(R.string.want_to_read) -> "3"
+                getString(R.string.on_hold), getString(R.string.paused) -> "4"
+                getString(R.string.completed) -> "5"
+                getString(R.string.dropped) -> "6"
+                else -> "7"
+            }
+        }
+    }
+
+    private fun mapStatus(status: Int): String {
+        return context.getString(
+            when (status) {
+                SManga.LICENSED -> R.string.licensed
+                SManga.ONGOING -> R.string.ongoing
+                SManga.COMPLETED -> R.string.completed
+                else -> R.string.unknown
+            }
+        )
+    }
     // SY <--
 }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt
index b6b86bc6b..5c6f3a3ad 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt
@@ -5,6 +5,7 @@ import android.content.Context
 import android.util.AttributeSet
 import android.view.View
 import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.TrackManager
@@ -25,6 +26,7 @@ class LibrarySettingsSheet(
     val filters: Filter
     private val sort: Sort
     private val display: Display
+    private val grouping: Grouping
 
     init {
         filters = Filter(activity)
@@ -35,6 +37,9 @@ class LibrarySettingsSheet(
 
         display = Display(activity)
         display.onGroupClicked = onGroupClickListener
+
+        grouping = Grouping(activity)
+        grouping.onGroupClicked = onGroupClickListener
     }
 
     fun refreshSort() {
@@ -44,13 +49,15 @@ class LibrarySettingsSheet(
     override fun getTabViews(): List<View> = listOf(
         filters,
         sort,
-        display
+        display,
+        grouping
     )
 
     override fun getTabTitles(): List<Int> = listOf(
         R.string.action_filter,
         R.string.action_sort,
-        R.string.action_display
+        R.string.action_display,
+        R.string.group
     )
 
     /**
@@ -198,6 +205,9 @@ class LibrarySettingsSheet(
 
             override fun onItemClicked(item: Item) {
                 item as Item.MultiStateGroup
+                // SY -->
+                if (item == dragAndDrop && preferences.groupLibraryBy().get() != LibraryGroup.BY_DEFAULT) return
+                // SY <--
                 val prevState = item.state
 
                 item.group.items.forEach {
@@ -355,6 +365,80 @@ class LibrarySettingsSheet(
         }
     }
 
+    // SY -->
+    inner class Grouping @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
+        Settings(context, attrs) {
+
+        init {
+            setGroups(listOf(InternalGroup()))
+        }
+
+        inner class InternalGroup : Group {
+            private val groupItems = mutableListOf<Item.DrawableSelection>()
+            private val db: DatabaseHelper = Injekt.get()
+            private val trackManager: TrackManager = Injekt.get()
+            private val hasCategories = db.getCategories().executeAsBlocking().size != 0
+
+            init {
+                val groupingItems = mutableListOf(
+                    LibraryGroup.BY_DEFAULT,
+                    LibraryGroup.BY_SOURCE,
+                    LibraryGroup.BY_STATUS
+                )
+                if (trackManager.hasLoggedServices()) {
+                    groupingItems.add(LibraryGroup.BY_TRACK_STATUS)
+                }
+                if (hasCategories) {
+                    groupingItems.add(LibraryGroup.UNGROUPED)
+                }
+                groupItems += groupingItems.map { id ->
+                    Item.DrawableSelection(
+                        id,
+                        this,
+                        LibraryGroup.groupTypeStringRes(id, hasCategories),
+                        LibraryGroup.groupTypeDrawableRes(id)
+                    )
+                }
+            }
+
+            override val header = null
+            override val items = groupItems
+            override val footer = null
+
+            override fun initModels() {
+                val groupType = preferences.groupLibraryBy().get()
+
+                items.forEach {
+                    it.state = if (it.id == groupType) {
+                        Item.DrawableSelection.SELECTED
+                    } else {
+                        Item.DrawableSelection.NOT_SELECTED
+                    }
+                }
+            }
+
+            override fun onItemClicked(item: Item) {
+                item as Item.DrawableSelection
+                if (item.id != LibraryGroup.BY_DEFAULT && preferences.librarySortingMode().get() == LibrarySort.DRAG_AND_DROP) {
+                    preferences.librarySortingMode().set(LibrarySort.ALPHA)
+                    preferences.librarySortingAscending().set(true)
+                    refreshSort()
+                }
+
+                item.group.items.forEach {
+                    (it as Item.DrawableSelection).state =
+                        Item.DrawableSelection.NOT_SELECTED
+                }
+                item.state = Item.DrawableSelection.SELECTED
+
+                preferences.groupLibraryBy().set(item.id)
+
+                item.group.items.forEach { adapter.notifyItemChanged(it) }
+            }
+        }
+    }
+    // SY <--
+
     open inner class Settings(context: Context, attrs: AttributeSet?) :
         ExtendedNavigationView(context, attrs) {
 
diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt
index 779d48de8..d7b84ab47 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt
@@ -109,6 +109,22 @@ open class ExtendedNavigationView @JvmOverloads constructor(
         }
 
         // SY -->
+        class DrawableSelection(val id: Int, group: Group, stringResId: Int, val drawable: Int) : MultiStateGroup(stringResId, group) {
+
+            companion object {
+                const val NOT_SELECTED = 0
+                const val SELECTED = 1
+            }
+
+            override fun getStateDrawable(context: Context): Drawable? {
+                return when (state) {
+                    SELECTED -> tintVector(context, drawable, R.attr.colorAccent)
+                    NOT_SELECTED -> tintVector(context, drawable, R.attr.colorOnSurface)
+                    else -> null
+                }
+            }
+        }
+
         class TriStateGroup(resId: Int, group: Group) : MultiStateGroup(resId, group) {
 
             companion object {
diff --git a/app/src/main/res/drawable/ic_progress_clock_24dp.xml b/app/src/main/res/drawable/ic_progress_clock_24dp.xml
new file mode 100644
index 000000000..a0f4b9cc0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_progress_clock_24dp.xml
@@ -0,0 +1,10 @@
+<!-- drawable/progress_clock.xml -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="#000"
+        android:pathData="M13,2.03V2.05L13,4.05C17.39,4.59 20.5,8.58 19.96,12.97C19.5,16.61 16.64,19.5 13,19.93V21.93C18.5,21.38 22.5,16.5 21.95,11C21.5,6.25 17.73,2.5 13,2.03M11,2.06C9.05,2.25 7.19,3 5.67,4.26L7.1,5.74C8.22,4.84 9.57,4.26 11,4.06V2.06M4.26,5.67C3,7.19 2.25,9.04 2.05,11H4.05C4.24,9.58 4.8,8.23 5.69,7.1L4.26,5.67M2.06,13C2.26,14.96 3.03,16.81 4.27,18.33L5.69,16.9C4.81,15.77 4.24,14.42 4.06,13H2.06M7.1,18.37L5.67,19.74C7.18,21 9.04,21.79 11,22V20C9.58,19.82 8.23,19.25 7.1,18.37M12.5,7V12.25L17,14.92L16.25,16.15L11,13V7H12.5Z" />
+</vector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_ungroup_24dp.xml b/app/src/main/res/drawable/ic_ungroup_24dp.xml
new file mode 100644
index 000000000..8ac8c7a22
--- /dev/null
+++ b/app/src/main/res/drawable/ic_ungroup_24dp.xml
@@ -0,0 +1,8 @@
+<!-- drawable/ungroup.xml -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path android:fillColor="#000" android:pathData="M2,2H6V3H13V2H17V6H16V9H18V8H22V12H21V18H22V22H18V21H12V22H8V18H9V16H6V17H2V13H3V6H2V2M18,12V11H16V13H17V17H13V16H11V18H12V19H18V18H19V12H18M13,6V5H6V6H5V13H6V14H9V12H8V8H12V9H14V6H13M12,12H11V14H13V13H14V11H12V12Z" />
+</vector>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings_sy.xml b/app/src/main/res/values/strings_sy.xml
index e5f00baf0..a8b564728 100644
--- a/app/src/main/res/values/strings_sy.xml
+++ b/app/src/main/res/values/strings_sy.xml
@@ -286,6 +286,11 @@
     <string name="tracked">Tracked</string>
     <string name="lewd">Lewd</string>
 
+    <!-- Library Grouping -->
+    <string name="tracking_status">Tracking status</string>
+    <string name="ungrouped">Ungrouped</string>
+    <string name="not_tracked">Not tracked</string>
+
     <!-- Favorites Sync -->
     <string name="sync_favorites">Sync favorites</string>
     <string name="favorites_sync_error">Favorites sync error</string>