Glimpse: Add search fragment
Change-Id: Ic21ce286314aa53e286ed1eab634b1d326afdfcf
diff --git a/app/src/main/java/org/lineageos/glimpse/flow/AlbumFlow.kt b/app/src/main/java/org/lineageos/glimpse/flow/AlbumFlow.kt
index 3f2212c..9eac117 100644
--- a/app/src/main/java/org/lineageos/glimpse/flow/AlbumFlow.kt
+++ b/app/src/main/java/org/lineageos/glimpse/flow/AlbumFlow.kt
@@ -28,16 +28,26 @@
override fun flowCursor(): Flow<Cursor?> {
val uri = MediaQuery.MediaStoreFileUri
val projection = MediaQuery.AlbumsProjection
- val imageOrVideo =
- (MediaStore.Files.FileColumns.MEDIA_TYPE eq MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE) or
- (MediaStore.Files.FileColumns.MEDIA_TYPE eq MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
+ val image =
+ MediaStore.Files.FileColumns.MEDIA_TYPE eq MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
+ val video =
+ MediaStore.Files.FileColumns.MEDIA_TYPE eq MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO
+ val imageOrVideo = when (bucketId) {
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_PHOTOS.id -> image
+
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_VIDEOS.id -> video
+
+ else -> image or video
+ }
val albumFilter = when (bucketId) {
MediaStoreBuckets.MEDIA_STORE_BUCKET_FAVORITES.id -> MediaStore.Files.FileColumns.IS_FAVORITE eq 1
MediaStoreBuckets.MEDIA_STORE_BUCKET_TRASH.id ->
MediaStore.Files.FileColumns.IS_TRASHED eq 1
- MediaStoreBuckets.MEDIA_STORE_BUCKET_REELS.id -> null
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_REELS.id,
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_PHOTOS.id,
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_VIDEOS.id -> null
else -> MediaStore.Files.FileColumns.BUCKET_ID eq Query.ARG
}
@@ -148,6 +158,14 @@
R.string.album_reels
)
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_PHOTOS.id -> context.getString(
+ R.string.album_photos
+ )
+
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_VIDEOS.id -> context.getString(
+ R.string.album_videos
+ )
+
else -> bucketDisplayName ?: Build.MODEL
},
media
diff --git a/app/src/main/java/org/lineageos/glimpse/flow/MediaFlow.kt b/app/src/main/java/org/lineageos/glimpse/flow/MediaFlow.kt
index db75169..abf0952 100644
--- a/app/src/main/java/org/lineageos/glimpse/flow/MediaFlow.kt
+++ b/app/src/main/java/org/lineageos/glimpse/flow/MediaFlow.kt
@@ -27,16 +27,26 @@
override fun flowCursor(): Flow<Cursor?> {
val uri = MediaQuery.MediaStoreFileUri
val projection = MediaQuery.MediaProjection
- val imageOrVideo =
- (MediaStore.Files.FileColumns.MEDIA_TYPE eq MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE) or
- (MediaStore.Files.FileColumns.MEDIA_TYPE eq MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
+ val image =
+ MediaStore.Files.FileColumns.MEDIA_TYPE eq MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
+ val video =
+ MediaStore.Files.FileColumns.MEDIA_TYPE eq MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO
+ val imageOrVideo = when (bucketId) {
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_PHOTOS.id -> image
+
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_VIDEOS.id -> video
+
+ else -> image or video
+ }
val albumFilter = when (bucketId) {
MediaStoreBuckets.MEDIA_STORE_BUCKET_FAVORITES.id -> MediaStore.Files.FileColumns.IS_FAVORITE eq 1
MediaStoreBuckets.MEDIA_STORE_BUCKET_TRASH.id ->
MediaStore.Files.FileColumns.IS_TRASHED eq 1
- MediaStoreBuckets.MEDIA_STORE_BUCKET_REELS.id -> null
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_REELS.id,
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_PHOTOS.id,
+ MediaStoreBuckets.MEDIA_STORE_BUCKET_VIDEOS.id -> null
else -> MediaStore.Files.FileColumns.BUCKET_ID eq Query.ARG
}
diff --git a/app/src/main/java/org/lineageos/glimpse/fragments/SearchFragment.kt b/app/src/main/java/org/lineageos/glimpse/fragments/SearchFragment.kt
new file mode 100644
index 0000000..99373dd
--- /dev/null
+++ b/app/src/main/java/org/lineageos/glimpse/fragments/SearchFragment.kt
@@ -0,0 +1,85 @@
+/*
+ * SPDX-FileCopyrightText: 2023 The LineageOS Project
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.lineageos.glimpse.fragments
+
+import android.os.Bundle
+import android.view.View
+import android.widget.LinearLayout
+import androidx.core.os.bundleOf
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import com.google.android.material.appbar.AppBarLayout
+import com.google.android.material.shape.MaterialShapeDrawable
+import org.lineageos.glimpse.R
+import org.lineageos.glimpse.ext.getViewProperty
+import org.lineageos.glimpse.ui.ListItem
+import org.lineageos.glimpse.utils.MediaStoreBuckets
+
+/**
+ * A fragment showing a search bar with categories.
+ * Use the [SearchFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class SearchFragment : Fragment(R.layout.fragment_search) {
+ // Views
+ private val appBarLayout by getViewProperty<AppBarLayout>(R.id.appBarLayout)
+ private val favoritesAlbumListItem by getViewProperty<ListItem>(R.id.favoritesAlbumListItem)
+ private val photosAlbumListItem by getViewProperty<ListItem>(R.id.photosAlbumListItem)
+ private val trashAlbumListItem by getViewProperty<ListItem>(R.id.trashAlbumListItem)
+ private val videosAlbumListItem by getViewProperty<ListItem>(R.id.videosAlbumListItem)
+
+ // Fragments
+ private val parentNavController by lazy {
+ requireParentFragment().requireParentFragment().findNavController()
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ val context = requireContext()
+
+ appBarLayout.statusBarForeground = MaterialShapeDrawable.createWithElevationOverlay(context)
+
+ photosAlbumListItem.setOnClickListener {
+ openAlbum(MediaStoreBuckets.MEDIA_STORE_BUCKET_PHOTOS)
+ }
+
+ videosAlbumListItem.setOnClickListener {
+ openAlbum(MediaStoreBuckets.MEDIA_STORE_BUCKET_VIDEOS)
+ }
+
+ favoritesAlbumListItem.setOnClickListener {
+ openAlbum(MediaStoreBuckets.MEDIA_STORE_BUCKET_FAVORITES)
+ }
+
+ trashAlbumListItem.setOnClickListener {
+ openAlbum(MediaStoreBuckets.MEDIA_STORE_BUCKET_TRASH)
+ }
+ }
+
+ private fun openAlbum(mediaStoreBucket: MediaStoreBuckets) {
+ parentNavController.navigate(
+ R.id.action_mainFragment_to_albumViewerFragment,
+ AlbumViewerFragment.createBundle(
+ bucketId = mediaStoreBucket.id
+ )
+ )
+ }
+
+ companion object {
+ private fun createBundle() = bundleOf()
+
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @return A new instance of fragment SearchFragment.
+ */
+ fun newInstance() = SearchFragment().apply {
+ arguments = createBundle()
+ }
+ }
+}
diff --git a/app/src/main/java/org/lineageos/glimpse/utils/MediaStoreBuckets.kt b/app/src/main/java/org/lineageos/glimpse/utils/MediaStoreBuckets.kt
index ad81e52..9805e6d 100644
--- a/app/src/main/java/org/lineageos/glimpse/utils/MediaStoreBuckets.kt
+++ b/app/src/main/java/org/lineageos/glimpse/utils/MediaStoreBuckets.kt
@@ -24,7 +24,17 @@
/**
* Reserved bucket ID for placeholders, throw an exception if this value is used.
*/
- MEDIA_STORE_BUCKET_PLACEHOLDER;
+ MEDIA_STORE_BUCKET_PLACEHOLDER,
+
+ /**
+ * Reels album, contains only photos.
+ */
+ MEDIA_STORE_BUCKET_PHOTOS,
+
+ /**
+ * Reels album, contains only videos.
+ */
+ MEDIA_STORE_BUCKET_VIDEOS;
val id = -0x0000DEAD - ((ordinal + 1) shl 16)
}
diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml
new file mode 100644
index 0000000..70476d5
--- /dev/null
+++ b/app/src/main/res/layout/fragment_search.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ SPDX-FileCopyrightText: 2023 The LineageOS Project
+ SPDX-License-Identifier: Apache-2.0
+-->
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.google.android.material.appbar.AppBarLayout
+ android:id="@+id/appBarLayout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:fitsSystemWindows="true"
+ app:liftOnScrollTargetViewId="@+id/searchScrollLayout">
+
+ <com.google.android.material.search.SearchBar
+ android:id="@+id/searchBar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ </com.google.android.material.appbar.AppBarLayout>
+
+ <androidx.core.widget.NestedScrollView
+ android:id="@+id/searchScrollLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/categoriesTitleTextView"
+ style="@style/TextAppearance.Material3.TitleLarge"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginHorizontal="17dp"
+ android:layout_marginVertical="22dp"
+ android:text="@string/categories_title" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <org.lineageos.glimpse.ui.ListItem
+ android:id="@+id/photosAlbumListItem"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:headlineText="@string/album_photos"
+ app:leadingIconImage="@drawable/ic_photo_size_select_actual" />
+
+ <org.lineageos.glimpse.ui.ListItem
+ android:id="@+id/videosAlbumListItem"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:headlineText="@string/album_videos"
+ app:leadingIconImage="@drawable/ic_play_circle_outline" />
+
+ <org.lineageos.glimpse.ui.ListItem
+ android:id="@+id/favoritesAlbumListItem"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:headlineText="@string/album_favorites"
+ app:leadingIconImage="@drawable/ic_star_border" />
+
+ <org.lineageos.glimpse.ui.ListItem
+ android:id="@+id/trashAlbumListItem"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:headlineText="@string/album_trash"
+ app:leadingIconImage="@drawable/ic_delete" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </androidx.core.widget.NestedScrollView>
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/navigation/main_fragment_navigation.xml b/app/src/main/res/navigation/main_fragment_navigation.xml
index a824736..888c9ab 100644
--- a/app/src/main/res/navigation/main_fragment_navigation.xml
+++ b/app/src/main/res/navigation/main_fragment_navigation.xml
@@ -21,4 +21,10 @@
android:label="@string/albums_title"
tools:layout="@layout/fragment_albums" />
+ <fragment
+ android:id="@+id/searchFragment"
+ android:name="org.lineageos.glimpse.fragments.SearchFragment"
+ android:label="@string/search_title"
+ tools:layout="@layout/fragment_search" />
+
</navigation>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 66079e4..24cdad9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -13,11 +13,14 @@
<string name="reels_title">Reels</string>
<string name="albums_title">Albums</string>
<string name="search_title">Search</string>
+ <string name="categories_title">Categories</string>
<!-- Album buckets -->
<string name="album_favorites">Favorites</string>
<string name="album_trash">Trash</string>
<string name="album_reels">Reels</string>
+ <string name="album_photos">Photos</string>
+ <string name="album_videos">Videos</string>
<!-- Album thumbnail -->
<plurals name="album_thumbnail_items">