Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate in-app gallery to Jetpack Compose #468

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e0e6d8a
Add verification metadata for Jetpack Compose
MHShetty Aug 30, 2024
8987892
Include compose with required dependencies
MHShetty Oct 13, 2024
eed34ce
Make CapturedItem serializable and parcelize able
MHShetty Oct 13, 2024
a78434c
Add method to attempt to delete CapturedItem
MHShetty Oct 13, 2024
937dc68
Add string resources
MHShetty Oct 13, 2024
6aaa47d
Add dialog composables
MHShetty Oct 13, 2024
35e2c1c
Add common utils and extension methods
MHShetty Oct 13, 2024
1054310
Add theme and typography for app
MHShetty Oct 13, 2024
9764256
Add media preview composables
MHShetty Oct 13, 2024
545eb73
Add serializer and navtypes for routes
MHShetty Oct 13, 2024
442ff77
Add QuickTooltip composable
MHShetty Oct 13, 2024
ecf04cd
Add generic and custom topbar composables
MHShetty Oct 13, 2024
7eaedc3
Add compose implementation for Video Player
MHShetty Oct 13, 2024
6cd3db2
Add CapturedItemsRepository to access and observe captured items
MHShetty Oct 13, 2024
eb357e3
Add Gallery screen composable, viewmodel and route
MHShetty Oct 13, 2024
87846a4
Add Extended Gallery screen composable, viewmodel and route
MHShetty Oct 13, 2024
26fdbfc
Add CameraApp composable
MHShetty Oct 13, 2024
70037e0
Use CameraApp composable
MHShetty Oct 13, 2024
f2cd30e
Remove system actionbar from in-app gallery
MHShetty Oct 13, 2024
3945469
Remove old unused code
MHShetty Oct 13, 2024
6082ee8
Add verification metadata
MHShetty Oct 13, 2024
440c828
Use no action bar theme
MHShetty Nov 27, 2024
bd0aa96
Add immersive experience in focus mode of InAppGallery
MHShetty Nov 28, 2024
e4b05dc
Separate UI-specific state from view model
MHShetty Nov 29, 2024
6a9a485
Add missing color
MHShetty Nov 29, 2024
93ba445
Disable predictive back gesture for MainActivity
MHShetty Dec 3, 2024
6d4e726
Push new gallery screen
MHShetty Dec 3, 2024
ceac35e
Replace search icon with grid icon
MHShetty Dec 3, 2024
7b7611a
Clear snackbar message on dispose
MHShetty Dec 3, 2024
86adf6d
Reduce controllerShowTimeoutMs of VideoPlayer
MHShetty Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ if (useKeystoreProperties) {
plugins {
id("com.android.application")
kotlin("android")
// The following plugin should have the same version as
// org.jetbrains.kotlin.android defined at project level
// gradle
id("org.jetbrains.kotlin.plugin.compose") version "2.0.10"
id("kotlin-parcelize")
id("org.jetbrains.kotlin.plugin.serialization")
}

java {
Expand Down Expand Up @@ -83,6 +89,11 @@ android {
buildFeatures {
viewBinding = true
buildConfig = true

compose = true
composeOptions {
kotlinCompilerExtensionVersion = "1.5.15"
}
}

lint {
Expand All @@ -105,4 +116,25 @@ dependencies {
implementation("androidx.camera:camera-extensions:$cameraVersion")

implementation("com.google.zxing:core:3.5.3")

val composeBom = platform("androidx.compose:compose-bom:2024.08.00")
implementation(composeBom)

implementation("androidx.compose.material3:material3:1.2.1")
implementation("androidx.navigation:navigation-compose:2.7.7")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material:material-icons-extended:1.7.2")

implementation("androidx.media3:media3-ui:1.4.0")
implementation("androidx.media3:media3-exoplayer:1.4.0")

implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.4")

implementation("androidx.navigation:navigation-compose:2.8.0")

implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1")

implementation("me.saket.telephoto:sub-sampling-image:0.13.0")
implementation("io.coil-kt.coil3:coil-compose-core:3.0.0-alpha10")
implementation("io.coil-kt.coil3:coil-video:3.0.0-alpha10")
}
5 changes: 2 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.App"
android:enableOnBackInvokedCallback="true"
tools:ignore="UnusedAttribute">

<!-- The main activity of the app (supports all modes) -->
Expand Down Expand Up @@ -162,14 +161,14 @@

<activity
android:name=".ui.activities.VideoPlayer"
android:theme="@style/Theme.Viewer"
android:theme="@style/Theme.Design.NoActionBar"
android:taskAffinity=".ui.activities.VideoPlayer"
android:excludeFromRecents="true"
android:exported="false"/>

<activity
android:name=".ui.activities.InAppGallery"
android:theme="@style/Theme.Viewer"
android:theme="@style/Theme.Design.NoActionBar"
android:taskAffinity=".ui.activities.InAppGallery"
android:excludeFromRecents="true"
android:exported="false"/>
Expand Down
48 changes: 30 additions & 18 deletions app/src/main/java/app/grapheneos/camera/CapturedItems.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package app.grapheneos.camera

import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
Expand All @@ -13,15 +12,21 @@ import android.provider.DocumentsContract
import android.provider.MediaStore
import android.util.Log
import app.grapheneos.camera.CamConfig.SettingValues
import app.grapheneos.camera.ui.composable.screen.serializer.CapturedItemSerializer
import app.grapheneos.camera.util.edit
import kotlin.jvm.Throws
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable

typealias ItemType = Int
const val ITEM_TYPE_IMAGE: ItemType = 0
const val ITEM_TYPE_VIDEO: ItemType = 1
const val IMAGE_NAME_PREFIX = "IMG_"
const val VIDEO_NAME_PREFIX = "VID_"

@Serializable(with = CapturedItemSerializer::class)
@Parcelize
class CapturedItem(
val type: ItemType,
val dateString: String,
Expand All @@ -45,12 +50,6 @@ class CapturedItem(
return "$prefix$dateString"
}

override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeByte(type.toByte())
dest.writeString(dateString)
uri.writeToParcel(dest, 0)
}

override fun hashCode(): Int {
return dateString.hashCode()
}
Expand All @@ -62,18 +61,31 @@ class CapturedItem(
return dateString == other.dateString
}

companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<CapturedItem> {
@SuppressLint("ParcelClassLoader")
override fun createFromParcel(source: Parcel): CapturedItem {
val type = source.readByte().toInt()
val dateString = source.readString()!!
val uri = Uri.CREATOR.createFromParcel(source)
return CapturedItem(type, dateString, uri)
}
companion object : Parceler<CapturedItem> {
override fun CapturedItem.write(dest: Parcel, flags: Int) {
dest.writeByte(type.toByte())
dest.writeString(dateString)
uri.writeToParcel(dest, 0)
}

override fun newArray(size: Int) = arrayOfNulls<CapturedItem>(size)
override fun create(source: Parcel): CapturedItem {
val type = source.readByte().toInt()
val dateString = source.readString()!!
val uri = Uri.CREATOR.createFromParcel(source)
return CapturedItem(type, dateString, uri)
}
}

fun delete(context: Context) : Boolean {
try {
return if (uri.authority == MediaStore.AUTHORITY) {
context.contentResolver.delete(uri, null, null) > 0
} else {
DocumentsContract.deleteDocument(context.contentResolver, uri)
}
} catch (e : Exception) {
e.printStackTrace()
return false
}
}

Expand Down
47 changes: 0 additions & 47 deletions app/src/main/java/app/grapheneos/camera/GSlideTransformer.kt

This file was deleted.

153 changes: 0 additions & 153 deletions app/src/main/java/app/grapheneos/camera/GallerySliderAdapter.kt

This file was deleted.

18 changes: 18 additions & 0 deletions app/src/main/java/app/grapheneos/camera/ktx/Context.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package app.grapheneos.camera.ktx

import android.app.Activity
import android.app.KeyguardManager
import android.content.Context

fun Context.isDeviceLocked() : Boolean {
val keyguardManager: KeyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
return keyguardManager.isKeyguardLocked
}

fun Context.requestDeviceUnlock() {
assert(this is Activity) {
"Please ensure that requestDeviceUnlock() is called by an activity context"
}
val keyguardManager: KeyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
keyguardManager.requestDismissKeyguard(this as Activity, null)
}
11 changes: 11 additions & 0 deletions app/src/main/java/app/grapheneos/camera/ktx/Dp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package app.grapheneos.camera.ktx

import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp

@Composable
fun Int.pxToDp() = with(LocalDensity.current) { [email protected]() }

@Composable
fun Dp.toPx() = with(LocalDensity.current) { [email protected]() }
Loading