diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt
index d97eb1330..0765d3ee1 100644
--- a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt
+++ b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt
@@ -23,13 +23,13 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
+import org.oxycblt.auxio.home.tabs.Tab
import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.settings.SettingsManager
-import org.oxycblt.auxio.settings.tabs.Tab
import org.oxycblt.auxio.ui.DisplayMode
import org.oxycblt.auxio.ui.Sort
diff --git a/app/src/main/java/org/oxycblt/auxio/settings/tabs/Tab.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/Tab.kt
similarity index 99%
rename from app/src/main/java/org/oxycblt/auxio/settings/tabs/Tab.kt
rename to app/src/main/java/org/oxycblt/auxio/home/tabs/Tab.kt
index d6b20e9d5..ba6a8918c 100644
--- a/app/src/main/java/org/oxycblt/auxio/settings/tabs/Tab.kt
+++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/Tab.kt
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-package org.oxycblt.auxio.settings.tabs
+package org.oxycblt.auxio.home.tabs
import org.oxycblt.auxio.ui.DisplayMode
import org.oxycblt.auxio.util.logE
diff --git a/app/src/main/java/org/oxycblt/auxio/settings/tabs/TabAdapter.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt
similarity index 98%
rename from app/src/main/java/org/oxycblt/auxio/settings/tabs/TabAdapter.kt
rename to app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt
index adfd59f91..636cf5e38 100644
--- a/app/src/main/java/org/oxycblt/auxio/settings/tabs/TabAdapter.kt
+++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-package org.oxycblt.auxio.settings.tabs
+package org.oxycblt.auxio.home.tabs
import android.annotation.SuppressLint
import android.view.MotionEvent
diff --git a/app/src/main/java/org/oxycblt/auxio/settings/tabs/TabCustomizeDialog.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt
similarity index 99%
rename from app/src/main/java/org/oxycblt/auxio/settings/tabs/TabCustomizeDialog.kt
rename to app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt
index 0a1b462b2..2183b275b 100644
--- a/app/src/main/java/org/oxycblt/auxio/settings/tabs/TabCustomizeDialog.kt
+++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-package org.oxycblt.auxio.settings.tabs
+package org.oxycblt.auxio.home.tabs
import android.os.Bundle
import android.view.LayoutInflater
diff --git a/app/src/main/java/org/oxycblt/auxio/settings/tabs/TabDragCallback.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabDragCallback.kt
similarity index 98%
rename from app/src/main/java/org/oxycblt/auxio/settings/tabs/TabDragCallback.kt
rename to app/src/main/java/org/oxycblt/auxio/home/tabs/TabDragCallback.kt
index fce3627f3..4f3942615 100644
--- a/app/src/main/java/org/oxycblt/auxio/settings/tabs/TabDragCallback.kt
+++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabDragCallback.kt
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-package org.oxycblt.auxio.settings.tabs
+package org.oxycblt.auxio.home.tabs
import android.graphics.Canvas
import androidx.recyclerview.widget.ItemTouchHelper
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt
index 341219632..5235d69c5 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt
@@ -94,6 +94,10 @@ class PlaybackFragment : Fragment() {
binding.playbackSong.isSelected = true
binding.playbackSeekBar.onConfirmListener = playbackModel::setPosition
+ binding.playbackPlayPause.post {
+ binding.playbackPlayPause.stateListAnimator = null
+ }
+
// --- VIEWMODEL SETUP --
playbackModel.song.observe(viewLifecycleOwner) { song ->
@@ -141,10 +145,6 @@ class PlaybackFragment : Fragment() {
}
}
- binding.playbackPlayPause.post {
- binding.playbackPlayPause.stateListAnimator = null
- }
-
logD("Fragment Created.")
return binding.root
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt
index efbb40868..081f5c965 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt
@@ -52,7 +52,7 @@ class PlaybackLayout @JvmOverloads constructor(
attrs: AttributeSet? = null,
defStyle: Int = 0
) : ViewGroup(context, attrs, defStyle) {
- enum class PanelState {
+ private enum class PanelState {
EXPANDED, COLLAPSED, HIDDEN, DRAGGING
}
@@ -85,8 +85,7 @@ class PlaybackLayout @JvmOverloads constructor(
private var lastInsets: WindowInsets? = null
/** The current panel state. Can be [PanelState.DRAGGING]*/
- var panelState = INIT_PANEL_STATE
- private set
+ private var panelState = INIT_PANEL_STATE
/** The last panel state before a drag event began. */
private var lastIdlePanelState = INIT_PANEL_STATE
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
index 6412f352a..85e4f49fb 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt
@@ -163,7 +163,7 @@ class PlaybackStateManager private constructor() {
when (mode) {
PlaybackMode.ALL_SONGS -> {
- val musicStore = MusicStore.requireInstance()
+ val musicStore = MusicStore.maybeGetInstance() ?: return
mParent = null
mQueue = musicStore.songs.toMutableList()
@@ -467,10 +467,9 @@ class PlaybackStateManager private constructor() {
* @param useLastSong Whether to use the previous song for the index calculations.
*/
private fun resetShuffle(keepSong: Boolean, useLastSong: Boolean) {
+ val musicStore = MusicStore.maybeGetInstance() ?: return
val lastSong = if (useLastSong) mQueue[mIndex] else mSong
- val musicStore = MusicStore.requireInstance()
-
mQueue = when (mPlaybackMode) {
PlaybackMode.ALL_SONGS ->
settingsManager.libSongSort.sortSongs(musicStore.songs).toMutableList()
@@ -605,7 +604,7 @@ class PlaybackStateManager private constructor() {
suspend fun restoreFromDatabase(context: Context) {
logD("Getting state from DB.")
- val musicStore = MusicStore.requireInstance()
+ val musicStore = MusicStore.maybeGetInstance() ?: return
val start: Long
val playbackState: PlaybackStateDatabase.SavedState?
diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt
index ff249f7dd..1a95d5bf1 100644
--- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt
@@ -33,10 +33,10 @@ import coil.Coil
import org.oxycblt.auxio.R
import org.oxycblt.auxio.accent.AccentDialog
import org.oxycblt.auxio.excluded.ExcludedDialog
+import org.oxycblt.auxio.home.tabs.TabCustomizeDialog
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.settings.pref.IntListPrefDialog
import org.oxycblt.auxio.settings.pref.IntListPreference
-import org.oxycblt.auxio.settings.tabs.TabCustomizeDialog
import org.oxycblt.auxio.util.isNight
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.showToast
diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt
index 039cdcb0b..ea326f870 100644
--- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt
+++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt
@@ -23,8 +23,8 @@ import android.content.SharedPreferences
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import org.oxycblt.auxio.accent.Accent
+import org.oxycblt.auxio.home.tabs.Tab
import org.oxycblt.auxio.playback.state.PlaybackMode
-import org.oxycblt.auxio.settings.tabs.Tab
import org.oxycblt.auxio.ui.DisplayMode
import org.oxycblt.auxio.ui.Sort
diff --git a/app/src/main/java/org/oxycblt/auxio/ui/Sort.kt b/app/src/main/java/org/oxycblt/auxio/ui/Sort.kt
index c1194a714..5ec294452 100644
--- a/app/src/main/java/org/oxycblt/auxio/ui/Sort.kt
+++ b/app/src/main/java/org/oxycblt/auxio/ui/Sort.kt
@@ -203,7 +203,7 @@ sealed class Sort(open val isAscending: Boolean) {
companion object {
private const val CONST_NAME = 0xA10C
- private const val CONST_ARTIST = 0xA10d
+ private const val CONST_ARTIST = 0xA10D
private const val CONST_ALBUM = 0xA10E
private const val CONST_YEAR = 0xA10F
diff --git a/app/src/main/res/anim/anim_nav_slide_down.xml b/app/src/main/res/anim/anim_nav_slide_down.xml
index be2049cd8..5400793bd 100644
--- a/app/src/main/res/anim/anim_nav_slide_down.xml
+++ b/app/src/main/res/anim/anim_nav_slide_down.xml
@@ -1,6 +1,9 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/anim_nav_slide_up.xml b/app/src/main/res/anim/anim_nav_slide_up.xml
index 8bbc16079..f5e26a8da 100644
--- a/app/src/main/res/anim/anim_nav_slide_up.xml
+++ b/app/src/main/res/anim/anim_nav_slide_up.xml
@@ -1,6 +1,9 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/anim_stationary.xml b/app/src/main/res/anim/anim_stationary.xml
index 10b171054..2f2b8501a 100644
--- a/app/src/main/res/anim/anim_stationary.xml
+++ b/app/src/main/res/anim/anim_stationary.xml
@@ -1,10 +1,10 @@
diff --git a/info/ARCHITECTURE.md b/info/ARCHITECTURE.md
index daef33c9e..d05be2794 100644
--- a/info/ARCHITECTURE.md
+++ b/info/ARCHITECTURE.md
@@ -1,40 +1,156 @@
-**Note:** Auxio is undergoing a major refactor right now. This document may not be fully up to date.
-It will be revamped when the refactor is complete.
-
# Architecture
-This document is designed to provide a simple overview of Auxio's architecture and where code resides/should reside. It will be updated as aspects about Auxio change.
+This document is designed to provide an overview of Auxio's architecture and design decisions. It will be updated as Auxio changes.
-#### Code structure
+## Core Facets
-Auxio's codebase is mostly centered around 4 different types of code.
+Auxio has a couple of core systems or concepts that should be understood when working with the codebase.
-- UIs: Fragments, RecyclerView items, and Activities are part of this class. All of them should have little data logic in them and should primarily focus on displaying information in their UIs.
-- ViewModels: These usually contain data and values that a UI can display, along with doing data processing. The data often takes the form of `MutableLiveData` or `LiveData`, which can be observed.
-- Shared Objects: These are the fundamental building blocks of Auxio, and exist at the process level. These are usually retrieved using `getInstance` or a similar function. Shared Objects should be avoided in UIs, as their volatility can cause problems. Its better to use a ViewModel and their exposed data instead.
-- Utilities: These are largely found in the `.ui`, `.music`, and `.coil` packages, taking the form of standalone or extension functions that can be used anywhere.
+#### Package Structure
-Ideally, UIs should only be talking to ViewModels, ViewModels should only be talking to the Shared Objects, and Shared Objects should only be talking to other shared objects. All objects can use the utility functions.
+Auxio's package structure is strictly feature-oriented. For example, playback code is exclusively in the `playback` package,
+detail code is exclusively in the `detail` package. Sub-packages can be related to the code it contains, such as `detail.recycler`
+for the detail UI adapters, or they can be related to a sub-feature, like `playback.queue` for the queue UI.
+
+A full run-down of Auxio's current package structure as of the latest version is shown below.
+
+```
+org.oxycblt.auxio # Main UIs
+├──.accent # Color Scheme UI + Systems
+├──.coil # Image loading components
+├──.detail # Album/Artist/Genre detail UIs
+│ └──.recycler # RecyclerView components for detail UIs
+├──.excluded # Excluded Directories UI + Systems
+├──.home # Home UI
+│ ├──.fastscroll # Fast scroller UI
+│ ├──.list # Home item lists
+│ └──.tabs # Home tab customization
+├──.music # Music data and loading
+├──.playback # Playback UI + Systems
+│ ├──.queue # Queue UI
+│ ├──.state # Playback state backend
+│ └──.system # System-side playback [Services, ExoPlayer]
+├──.search # Search UI
+├──.settings # Settings UI + Systems
+│ └──.pref # Int preference add-on
+├──.ui # Shared views and models
+├──.util # Shared utilities
+└──.widgets # AppWidgets
+```
+
+Each package is gone over in more detail later on.
#### UI Structure
-Auxio only has one activity, that being `MainActivity`. When adding a new UI, it should be added as a `Fragment` or a `RecyclerView` item depending on the situation.
+Auxio only has one activity, `MainActivity`. Do not try to add more activities to the codebase. Instead, a new UI
+should be added as a new `Fragment` implementation and added to one of the two navigation graphs:
-Databinding should *always* be used instead of `findViewById`. Use `by memberBinding` if the binding needs to be a member variable in order to avoid memory leaks.
+- `nav_main`: Navigation *from* `MainFragment`
+- `nav_explore`: Navigation *in* `MainFragment`
-Usually, fragment creation is done in `onCreateView`, and organized into three parts:
+Fragments themselves are organized in order of lifecycle. So the first override would be `onCreate`, followed by
+`onCreateView`, and so on. `onCreateView` is where all view instantiation and configuration takes place, and
+is separated into three phases:
- Create variables [Bindings, Adapters, etc]
- Set up the UI
- Set up LiveData observers
-When creating a ViewHolder for a `RecyclerView`, one should use `BaseViewHolder` to standardize the binding process and automate some code shared across all ViewHolders.
+`findViewById` is to **only** be used when interfacing with non-Auxio views. Otherwise, viewbinding should be
+used in all cases. If one needs to keep track of a viewbinding outside of `onCreateView`, then one can declare
+a binding `by memberBinding(BindingClass::inflate)` in order to have a binding that properly disposes itself
+on lifecycle events.
-Data is often bound using Binding Adapters, which are XML attributes assigned in layout files that can automatically display data, usually written as `app:bindingAdapterName="@{data}"`. Its recommended to use these instead of duplicating code manually.
+At times it may be more appropriate to use a `View` instead of a full blown fragment. This is okay as long as
+viewbinding is still used.
-#### Integers
+When creating a ViewHolder for a `RecyclerView`, one should use `BaseViewHolder` to standardize the binding process
+and automate some code shared across all ViewHolders. The only exceptions to this case are for ViewHolders that
+correspond to non-`BaseModel` data, in which a normal ViewHolder can be used instead.
-Integer representations of data/ui elements are used heavily in Auxio.
+Data is often bound using Binding Adapters, which are XML attributes assigned in layout files that can automatically
+display data, usually written as `app:bindingAdapterName="@{data}"`. Its recommended to use these instead of applying
+the attributes directly unless absolutely necessary. Usually it's okay to apply data programmatically if you begin
+to duplicate layouts simply because they apply to different data objects, such as the detail UIs.
+
+#### Object communication
+
+Auxio's codebase is mostly centered around 4 different types of code that communicates with each-other.
+
+- UIs: Fragments, RecyclerView items, and Activities are part of this class. All of them should have little data logic
+in them and should primarily focus on displaying information in their UIs.
+- ViewModels: These usually contain data and values that a UI can display, along with doing data processing. The data
+often takes the form of `MutableLiveData` or `LiveData`, which can be observed.
+- Shared Objects: These are the fundamental building blocks of Auxio, and exist at the process level. These are usually
+retrieved using `getInstance` or a similar function. Shared Objects should be avoided in UIs, as their volatility can
+cause problems. Its better to use a ViewModel and their exposed data instead.
+- Utilities: These are largely found in the `.util` and `.coil` packages, taking the form of standalone or extension
+functions that can be used anywhere.
+
+Ideally, UIs should only be talking to ViewModels, ViewModels should only be talking to the Shared Objects, and Shared Objects
+should only be talking to other shared objects. All objects can use the utility functions where appropriate.
+
+#### Data objects
+
+Auxio represents data in multiple ways.
+
+`BaseModel` is the base class for most music and UI data in Auxio, with a single ID field meant to mark it as unique.
+
+It has the following implementations:
+- `Music` is a `BaseModel` that represents music. It adds a `name` field that represents the raw name of the music (from `MediaStore`).
+- `MusicParent` is a type of `Music` that contains children. It adds a `resolveName` field that converts the raw `MediaStore` name
+to a name that can be used in UIs.
+- `Header` and `ActionHeader` are UI data objects that represent a header item. `Header` corresponds to a simple header with no action,
+while `ActionHeader` corresponds to an action with a dedicated icon, such as with sorting.
+
+Other data types represent a specific UI configuration or state:
+
+- Sealed classes like `Sort` and `HeaderString` contain data with them that can be modified.
+- Enums like `DisplayMode` and `LoopMode` only contain static data, such as a string resource.
+
+#### Music Access
+
+All music on a system is asynchronously indexed into the shared object `MusicStore`. Because of this, **`MusicStore` may not be available at all times**.
+
+- ViewModels should try to await or gracefully exit if music is not available
+- In the case that a ViewModel needs a `MusicStore` instance to function, an instance can be required. This should be done sparingly.
+- Other shared objects that rely on `MusicStore` [like `PlaybackStateManager`] will no-op if music is not available.
+
+#### Playback System
+
+Auxio's playback system is somewhat unorthodox, as it avoids much of the android-provided APIs in favor of a more controllable and sensible system.
+The diagram below highlights the overall structure and connections:
+
+```
+ [Requests update from]
+ ┌─────────────────────────────────────────────────────────────────────────────────┐
+ │ │
+ ┌──────────────────── PlaybackService ──────────────────── WidgetController ──────────────────── WidgetProvider ┘
+ │ │ [Contains] [Controls]
+PlaybackStateManager [Communicates with] │
+ │ │ [Contains]
+ │ │
+ │ ├ Notification
+ │ ├ MediaSession
+ │ └ Player
+ │
+ └──────────────────── PlaybackViewModel ───────────────────── UIs
+ [Communicates With]
+```
+
+`PlaybackStateManager` is the shared object that contains the master copy of the playback state, doing all operations on it. This object should
+***NEVER*** be used in a UI, as it does not sanitize input and can cause major problems if a Volatile UI interacts with it. It's callback system
+is also prone to memory leaks if not cleared when done. `PlaybackViewModel` should be used instead, as it exposes stable data and safe functions
+that UIs can use to interact with the playback state.
+
+`PlaybackService`'s job is to use the playback state to manage the ExoPlayer instance, the notification, the widget, and also modify the state depending on
+system events, such as when a button is pressed on a headset. It should **never** be bound to, mostly because there is no need given that
+`PlaybackViewModel` exposes the same data in a much safer fashion. `PlaybackService` also controls the `PlaybackSessionConnector`, `AudioReactor`,
+and `WidgetController` classes, which manage the `MediaSession`, Audio Focus, and Widgets respectively.
+
+#### Data Integers
+
+Integer representations of data/UI elements are used heavily in Auxio, primarily for efficiency.
To prevent any strange bugs, all integer representations must be unique. A table of all current integers used are shown below:
```
@@ -56,7 +172,6 @@ To prevent any strange bugs, all integer representations must be unique. A table
0xA00C | GenreSongViewHolder
0xA00D | QueueSongViewHolder
-0xA00E | PlayPauseViewHolder
0xA0A0 | Auxio notification code
0xA0C0 | Auxio request code
@@ -78,41 +193,28 @@ To prevent any strange bugs, all integer representations must be unique. A table
0xA10A | DisplayMode.SHOW_ALBUMS
0xA10B | DisplayMode.SHOW_SONGS
-0xA10C | SortMode.ASCENDING
-0xA10D | SortMode.DESCENDING
-0xA10E | SortMode.ARTIST
-0xA10F | SortMode.ALBUM
-0xA110 | SortMode.YEAR
+0xA10C | Sort.Name
+0xA10D | Sort.Artist
+0xA10E | Sort.Album
+0xA10F | Sort.Year
```
-#### Package structure overview
+Some datatypes [like `Tab` and `Sort`] have even more fine-grained integer representations for other information. More information can be found in
+the documentation for these datatypes.
-Auxio's package structure is mostly based around the features, and then any sub-features or components involved with that. There are some shared packages however. A diagram of the package structure is shown below:
+## Package-by-package rundown
-```
-org.oxycblt.auxio # Main UI's and utilities
-├──.accent # Accent UI + Systems
-├──.coil # Fetchers and utilities for Coil, contains binding adapters than be used in the user interface.
-├──.blacklist # Excluded Directories UI/Systems
-├──.database # Databases and their items for Auxio
-├──.detail # UIs for more album/artist/genre details
-│ └──.adapters # RecyclerView adapters for the detail UIs, which display the header information and items
-├──.library # Library UI
-├──.loading # Loading UI
-├──.music # Music storage and loading
-├──.playback # Playback UI and systems
-│ ├──.queue # Queue user interface
-│ ├──.state # Backend/Modes for the playback state
-│ └──.system # System-side playback [Services, ExoPlayer]
-├──.recycler # Shared RecyclerView utilities and modes
-│ └──.viewholders # Shared ViewHolders and ViewHolder utilities
-├──.search # Search UI
-├──.settings # Settings UI and systems
-│ └──.ui # Settings-Related UIs
-├──.songs # Songs UI
-├──.ui # Shared user interface utilities
-└──.widgets # Widgets
-```
+#### `org.oxycblt.auxio`
+
+This is the root package and contains the application instance and the landing UIs. This should be kept sparse with most other code being placed
+into a package.
+
+#### `.accent`
+
+This package is responsible for Auxio's color schemes, internally known as accents due to legacy code.
+It contains an object that represents the attributes of an accent, but this should be avoided in favor of
+resolving color attributes directly, such as `colorPrimary`. This package also contains the UIs for picking
+an accent.
#### `.coil`
@@ -123,101 +225,91 @@ org.oxycblt.auxio # Main UI's and utilities
- `app:genreImage`: Binding Adapter that will load the genre image
- `loadBitmap`: Function that will take a song and return a bitmap, this should not be used in anything UI related, that is what the binding adapters above are for.
-This should be enough to cover most use cases in Auxio. There are also fetchers for artist/genre images and album covers, but these are not used outside of the module.
+This should be enough to cover most use cases in Auxio.
-#### `.database`
-
-This is the general repository for databases in Auxio, along with their entities. All databases use `SQLiteOpenHelper`, with all database entities having their keys in a `companion object`.
+Internally, multiple fetchers are provided to transform `Music` instances into images. All of these fetchers inherit `AuxioFetcher`, which implements
+the necessary methods for loading album artwork and creating the mosaics shown in artist/genre images.
#### `.detail`
-Contains all the detail UIs for some data types in Auxio. All detail user interfaces share the same base layout (A Single RecyclerView) and only change the adapter/data being used. The adapters display both the header with information and the child items of the item itself, usually with a data list similar to this:
+Contains all the detail UIs for some data types in Auxio. All detail user interfaces share the same base layout (A Single RecyclerView) and
+only change the adapter/data being used. The adapters display both the header with information and the child items of the item itself, usually
+with a data list similar to this:
-`Item being displayed | Child Item | Child Item | Child Item...`
+`Item being displayed | Header Item | Child Item | Child Item | Child Item...`
-`DetailViewModel` acts as the holder for the currently displaying items, along with having the `navToItem` LiveData that coordinates menu/playback navigation [Such as when a user presses "Go to artist"]
+Each adapter instance also handles the highlighting of the currently playing item in the detail menu.
-#### `.library`
+`DetailViewModel` acts as the holder for the currently displaying items, along with having the `navToItem` LiveData that coordinates menu/playback
+navigation [Such as when a user presses "Go to artist"]
-The UI and adapters for the library view in Auxio, `LibraryViewModel` handles the sorting and which data to display in the fragment, while `LibraryFragment` and `LibraryAdapter` displays the data.
+#### `.excluded`
+
+This package is responsible for the excluded directory system. It contains the database of excluded directories and the dialog that appears when
+editing them.
+
+**Note:** Certain naming in this package might not line up with the current name of the package. This is because updating those names would break
+compatibility with previous versions of Auxio.
+
+#### `.home`
+
+This package contains the components for the "home" UI in Auxio, or the UI that the user first sees when they open the app.
+
+- The base package contains the top-level components that manage the FloatingActionButton, AppBar, and ViewPager instances.
+- The `fastscroll` package contains the fast scroll component used in each list of music
+- The `list` package contains the individual fragments for each list of music. These are all placed in the top-level ViewPager instance.
+- The `tabs` package contains the data representation of an individual library tab and the UI's for editing them.
#### `.music`
-The music loading system is based off of `MediaStore`, and loads the entire library into a variety of data objects.
-
-All music objects inherit `BaseModel`, which guarantees that all music has both an ID and a name.
-
-- Songs are the most basic element, with them having a reference to their album and genre.
-- Albums contain a list of their songs and their parent artist.
-- Artists contain a list of songs, a list of albums, and their most prominent genre.
-- Genres contain a list of songs, its preferred to use `displayName` with genres as that will convert the any numbered names into non-numbered names.
-
-`BaseModel` can be used as an argument type to specify that any music type, while `Parent` can be used as an argument type to only specify music objects that have child items, such as albums or artists.
+This package contains all `BaseModel` implementations and the music loading implementation. This also includes `Header`/`ActionHeader`, as those
+data objects have to inherit `BaseModel` so that they can be placed alongside `Music` instances in `RecyclerView` instances.
#### `.playback`
-Auxio's playback system is somewhat unorthodox, as it avoids a lot of the built-in android code in favor of a more understandable and controllable system. Its structured around a couple of objects, the connections being highlighted in this diagram.
+This module not only contains the playback system described above, but also multiple other components:
-```
- Playback UIs Queue UI PlaybackService
- │ │ │
- │ │ │
- PlaybackViewModel─────┘ │
- │ │
- │ │
-PlaybackStateManager───────────────────┘
-```
+- `queue` contains the Queue UI and it's fancy item transitions
+- `state` contains the core playback state system
+- `system` contains the system-facing playback system
-`PlaybackStateManager` is the shared object that contains the master copy of the playback state, doing all operations on it. This object should ***NEVER*** be used in a UI, as it does not sanitize input and can cause major problems if a Volatile UI interacts with it. It's callback system is also prone to memory leaks if not cleared when done. `PlaybackViewModel` should be used instead, as it exposes stable data and safe functions that UIs can use to interact with the playback state.
-
-`PlaybackService`'s job is to use the playback state to manage the ExoPlayer instance, the notification, and also modify the state depending on system events, such as when a button is pressed on a headset. It should **never** be bound to, mostly because there is no need given that `PlaybackViewModel` exposes the same data in a much safer fashion. `PlaybackService` also controls the `PlaybackSessionConnector`, `AudioReactor`, and `WidgetController` classes, which manage the `MediaSession`, Audio Focus, and Widgets respectively.
-
-#### `.recycler`
-
-Shared RecyclerView utilities, often for adapters and ViewHolders. Important ones to note are `DiffCallback`, which acts as a reusable differ callback based off of `BaseModel` for `ListAdapter`s, and the shared ViewHolders for each data type, such as `SongViewHolder` or `HeaderViewHolder`.
-
-#### `.settings`
-
-The settings system is primarily based off of `SettingsManager`, a wrapper around `SharedPreferences`. This allows settings to be read/written in a much simpler/safer manner and without a context being needed. The Settings UI is largely contained in `SettingsListFragment`, while the sub-packages contain sub-uis related to the `SettingsListFragment`, such as the custom list preference `IntListPreference` and the about dialog.
+The most important part of this module is `PlaybackLayout`, which is a custom `ViewGroup` that implements the playback bar and it's ability to
+slide up into the full playback view. `MainFragment` controls this `ViewGroup`, more specifically the bar view, as it can't be an independent
+fragment due to a couple of annoying reasons.
#### `.search`
-Package for Auxio's search functionality, `SearchViewHolder` handles the data results and filtering while `SearchFragment`/`SearchAdapter` handles the display of the results and user input.
+Package for Auxio's search functionality, `SearchViewHolder` handles the data results and filtering while `SearchFragment`/`SearchAdapter` handles the
+display of the results and user input.
-#### `.songs`
+#### `.settings`
-Package for the songs UI, there is no data management here, only a user interface.
+The settings system is primarily based off of `SettingsManager`, a wrapper around `SharedPreferences`. This allows settings to be read/written in a
+much simpler/safer manner and without a context being needed. The Settings UI is largely contained in `SettingsListFragment`, while the `pref`
+sub-package contains `IntListPreference`, which allows Auxio's integer representations to be used with the preference UI. The about dialog
+also resides in this package.
#### `.ui`
-Shared User Interface utilities. This is primarily made up of convenience/extension functions relating to Views, Resources, Configurations, and Contexts. It also contains some dedicated utilities, such as:
-- The Accent Management system
+Shared views and view configuration models. This contains:
+
+- Customized views such as `EdgeAppBarLayout` and `EdgeRecyclerView`, which add some extra functionality not provided by default
+- Configuration models like `DisplayMode` and `Sort`, which are used in many places but aren't tied to a specific feature.
- `newMenu` and `ActionMenu`, which automates menu creation for most data types
- `memberBinding` and `MemberBinder`, which allows for ViewBindings to be used as a member variable without memory leaks or nullability issues.
+#### `.util`
+
+Shared utilities. This is primarily for QoL when developing Auxio. Documentation is provided on each method.
+
#### `.widgets`
-The widget sub-module. This module differs heavily from the rest of Auxio, as widget UIs can't be controlled in the same
-way that UIs in the main process can.
-
-Widgets are controlled by two pieces of code:
-
-- `WidgetProvider`, which provides the widget layouts to the system
-- `WidgetController`, which acts as an intermediary between the Auxio process and the widget [ex. Monitoring the playback state]
-
-The widget update process is described in this diagram:
-
-```
-WidgetController<──────────PlaybackService
- │ Controls ^
- │ │
- │ Updates │
- │ │
- │ │
- v Requests Update │
- WidgetProvider───────────────────┘
-```
+This package contains Auxio's AppWidget implementation, which deviates from other AppWidget implementations by packing multiple
+different layouts into a single widget and then switching between them depending on the widget size.
When `WidgetProvider` creates a layout, it first turns the `PlaybackStateManager` instance into a `WidgetState`, which is
an immutable version of the playback state that negates some of the problems with using a shared object here. It then picks
-a layout [e.g "Form"] depending on its current dimensions and applies the `WidgetState` object to that.
\ No newline at end of file
+a layout [e.g "Form"] depending on its current dimensions and applies the `WidgetState` object to that.
+
+**Note:** The AppWidget implementation violates UI conventions by directly interfacing with coil and `PlaybackStateManager`.
+This is required due to `RemoteView` limitations.
\ No newline at end of file
diff --git a/info/FAQ.md b/info/FAQ.md
index 57aa4d7bd..12d9a6445 100644
--- a/info/FAQ.md
+++ b/info/FAQ.md
@@ -11,13 +11,13 @@ Auxio is not and will never be on the play store due to it being a proprietary a
This is probably caused by one of two reasons:
-1. If other players like Phonograph or Retro Music load it correctly, then Auxio has a bug and it should be [reported](https://github.com/OxygenCobalt/Auxio/issues).
+1. If other players like Phonograph, Retro Music, or Music Player GO load it correctly, then Auxio has a bug and it should be [reported](https://github.com/OxygenCobalt/Auxio/issues).
2. If the aforementioned players don't work, but players like Vanilla Music and VLC do, then it's a problem with the Media APIs that Auxio relies on. There is nothing I can do about it.
#### I have a large library and Auxio takes really long to load it!
This is expected since reading media takes awhile, especially with libraries containing 10k songs or more.
-I do hope to mitigate this in the future by allowing one to customize the music loader to optimize for speed instead of accuracy.
+I hope to mitigate this in the future by allowing one to customize the music loader to optimize for speed instead of accuracy.
#### Why ExoPlayer?
@@ -27,22 +27,9 @@ ability to be extended to music sources outside of local files. You can read mor
#### What formats does Auxio support?
-As per the [Supported ExoPlayer Formats](https://exoplayer.dev/supported-formats.html), Auxio supports the following:
-
-✅ = Supported
-
-👎 = Not supported well
-
-| Format | Supported | Comments |
-|--------|-----------|-----------
-| MP4 | ✅ | |
-| MP3 | ✅ | |
-| MKA | ✅ | |
-| OGG | ✅ | Containing Vorbis, Opus, and FLAC |
-| WAV | ✅ | |
-| MPEG | ✅ | |
-| AAC | ✅ | |
-| FLAC | 👎 | Supported on Android 8.1 or newer. Auxio must be patched with the [FLAC Extension](https://github.com/google/ExoPlayer/tree/release-v2/extensions/flac) on lower versions. |
+As per the [Supported ExoPlayer Formats](https://exoplayer.dev/supported-formats.html), Auxio supports
+MP4, MP3, MKA, OGG, WAV, MPEG, ACC on all versions of Android. FLAC files are supported on Android 8.1
+or newer, on lower versions Auxio must be patched with the [FLAC Extension](https://github.com/google/ExoPlayer/tree/release-v2/extensions/flac).
#### Why are accents lighter/less saturated in dark mode?