Fix gradle format task.

This commit is contained in:
Greyson Parrelli
2026-02-16 14:22:44 -05:00
committed by Alex Hart
parent 9cefe0bc04
commit b48b1f031e
57 changed files with 164 additions and 186 deletions

View File

@@ -1,13 +1,11 @@
package org.signal.camera.demo
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
@@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("org.signal.camera.demo", appContext.packageName)
}
}
}

View File

@@ -24,4 +24,4 @@ class MainActivity : ComponentActivity() {
}
}
}
}
}

View File

@@ -1,22 +1,15 @@
package org.signal.camera.demo
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Composable
import androidx.navigation3.runtime.NavKey
import androidx.compose.ui.Modifier
import androidx.navigation3.runtime.NavBackStack
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.scene.Scene
import androidx.navigation3.ui.NavDisplay
import org.signal.camera.demo.screens.gallery.GalleryScreen
import org.signal.camera.demo.screens.imageviewer.ImageViewerScreen
@@ -42,24 +35,24 @@ fun NavGraph(
modifier: Modifier = Modifier
) {
val backStack = rememberNavBackStack(Screen.Main)
@Suppress("UNCHECKED_CAST")
val typedBackStack = backStack as NavBackStack<Screen>
NavDisplay(
backStack = backStack,
modifier = modifier,
transitionSpec = {
// Gallery slides up from bottom
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(500)
) togetherWith
// Camera stays in place and fades out
slideOutHorizontally (
targetOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(500)
)
// Camera stays in place and fades out
slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(500)
)
},
popTransitionSpec = {
// Camera slides back in from left
@@ -67,11 +60,11 @@ fun NavGraph(
initialOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(500)
) togetherWith
// Gallery slides out to right
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(500)
)
// Gallery slides out to right
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(500)
)
},
predictivePopTransitionSpec = { progress ->
// Camera slides back in from left (predictive with progress)
@@ -79,21 +72,21 @@ fun NavGraph(
initialOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(500)
) togetherWith
// Gallery slides out to right (predictive with progress)
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(500)
)
// Gallery slides out to right (predictive with progress)
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(500)
)
},
entryProvider = entryProvider {
addEntryProvider(
key = Screen.Main,
contentKey = Screen.Main,
key = Screen.Main,
contentKey = Screen.Main,
metadata = emptyMap()
) { screen: Screen ->
MainScreen(backStack = typedBackStack)
}
addEntryProvider(
key = Screen.Gallery,
contentKey = Screen.Gallery,
@@ -101,7 +94,7 @@ fun NavGraph(
) { screen: Screen ->
GalleryScreen(backStack = typedBackStack)
}
addEntryProvider(
key = Screen.ImageViewer,
contentKey = Screen.ImageViewer,
@@ -109,7 +102,7 @@ fun NavGraph(
) { screen: Screen ->
ImageViewerScreen(backStack = typedBackStack)
}
addEntryProvider(
key = Screen.VideoViewer,
contentKey = Screen.VideoViewer,

View File

@@ -5,8 +5,6 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
@@ -17,10 +15,10 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.PlayArrow
@@ -59,11 +57,11 @@ fun GalleryScreen(
val context = LocalContext.current
val state = viewModel.state.value
var showDeleteDialog by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
viewModel.loadMedia(context)
}
// Delete confirmation dialog
if (showDeleteDialog) {
AlertDialog(
@@ -92,7 +90,7 @@ fun GalleryScreen(
}
)
}
Box(
modifier = Modifier
.fillMaxSize()
@@ -154,7 +152,7 @@ fun GalleryScreen(
}
}
}
// Delete all button at bottom (only show when there are items)
if (state.mediaItems.isNotEmpty()) {
Button(
@@ -196,7 +194,7 @@ private fun MediaThumbnail(
scaleType = GlideImageScaleType.CENTER_CROP,
modifier = Modifier.fillMaxSize()
)
if (mediaItem.isVideo) {
Box(
modifier = Modifier

View File

@@ -19,10 +19,10 @@ class GalleryScreenViewModel : ViewModel() {
private val _state: MutableState<GalleryScreenState> = mutableStateOf(GalleryScreenState())
val state: State<GalleryScreenState>
get() = _state
fun loadMedia(context: Context) {
_state.value = _state.value.copy(isLoading = true, error = null)
viewModelScope.launch {
try {
val mediaItems = loadMediaFromInternalStorage(context)
@@ -40,7 +40,7 @@ class GalleryScreenViewModel : ViewModel() {
}
}
}
fun deleteAllMedia(context: Context) {
viewModelScope.launch {
try {
@@ -56,14 +56,14 @@ class GalleryScreenViewModel : ViewModel() {
}
}
}
private suspend fun loadMediaFromInternalStorage(context: Context): List<MediaItem> = withContext(Dispatchers.IO) {
val galleryDir = File(context.filesDir, GALLERY_FOLDER)
if (!galleryDir.exists()) {
return@withContext emptyList()
}
galleryDir.listFiles()
?.filter { it.isFile }
?.mapNotNull { file ->
@@ -80,23 +80,23 @@ class GalleryScreenViewModel : ViewModel() {
?.sortedByDescending { it.lastModified }
?: emptyList()
}
private suspend fun deleteAllMediaFromInternalStorage(context: Context): Int = withContext(Dispatchers.IO) {
val galleryDir = File(context.filesDir, GALLERY_FOLDER)
if (!galleryDir.exists()) {
return@withContext 0
}
val files = galleryDir.listFiles() ?: return@withContext 0
var deletedCount = 0
files.forEach { file ->
if (file.isFile && file.delete()) {
deletedCount++
}
}
deletedCount
}
}

View File

@@ -6,19 +6,19 @@ sealed class MediaItem {
abstract val file: File
abstract val name: String
abstract val lastModified: Long
data class Image(
override val file: File,
override val name: String = file.name,
override val lastModified: Long = file.lastModified()
) : MediaItem()
data class Video(
override val file: File,
override val name: String = file.name,
override val lastModified: Long = file.lastModified()
) : MediaItem()
val isImage: Boolean get() = this is Image
val isVideo: Boolean get() = this is Video
}

View File

@@ -36,18 +36,18 @@ fun ImageViewerScreen(
backStack: NavBackStack<Screen>
) {
val selectedMedia = org.signal.camera.demo.MediaSelectionHolder.selectedMedia
if (selectedMedia == null || selectedMedia !is MediaItem.Image) {
// No image selected, go back
backStack.removeLastOrNull()
return
}
val imageFile = selectedMedia.file
var scale by remember { mutableFloatStateOf(1f) }
var offset by remember { mutableStateOf(Offset.Zero) }
Box(
modifier = Modifier
.fillMaxSize()
@@ -83,7 +83,7 @@ fun ImageViewerScreen(
)
)
}
// Back button
IconButton(
onClick = { backStack.removeLastOrNull() },

View File

@@ -5,6 +5,7 @@ package org.signal.camera.demo.screens.main
import android.Manifest
import android.os.Build
import android.widget.Toast
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@@ -25,35 +26,34 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation3.runtime.NavBackStack
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.MultiplePermissionsState
import com.google.accompanist.permissions.PermissionState
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import androidx.compose.foundation.background
import androidx.compose.ui.graphics.Color
import androidx.navigation3.runtime.NavBackStack
import org.signal.camera.demo.Screen
import org.signal.camera.hud.StandardCameraHudEvents
import org.signal.camera.CameraScreen
import org.signal.camera.CameraScreenEvents
import org.signal.camera.CameraScreenViewModel
import org.signal.camera.demo.Screen
import org.signal.camera.hud.StandardCameraHud
import org.signal.camera.hud.StandardCameraHudEvents
@Composable
fun MainScreen(
backStack: NavBackStack<Screen>,
viewModel: MainScreenViewModel = viewModel(),
viewModel: MainScreenViewModel = viewModel()
) {
val cameraViewModel: CameraScreenViewModel = viewModel()
val permissions = buildList {
add(Manifest.permission.CAMERA)
add(Manifest.permission.RECORD_AUDIO)
if (Build.VERSION.SDK_INT >= 33) {
add(Manifest.permission.READ_MEDIA_IMAGES)
add(Manifest.permission.READ_MEDIA_VIDEO)
@@ -61,7 +61,7 @@ fun MainScreen(
add(Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
val permissionsState = rememberMultiplePermissionsState(permissions = permissions)
val context = LocalContext.current
@@ -126,7 +126,7 @@ fun MainScreen(
}
)
}
is StandardCameraHudEvents.VideoCaptureStopped-> {
is StandardCameraHudEvents.VideoCaptureStopped -> {
cameraViewModel.stopRecording()
}
is StandardCameraHudEvents.GalleryClick -> {
@@ -155,7 +155,7 @@ fun MainScreen(
)
}
}
// QR Code Dialog
if (qrCodeContent != null) {
AlertDialog(

View File

@@ -5,8 +5,8 @@ import android.graphics.Bitmap
sealed interface MainScreenEvents {
data class SavePhoto(val context: Context, val bitmap: Bitmap) : MainScreenEvents
data class VideoSaved(val result: org.signal.camera.VideoCaptureResult) : MainScreenEvents
data object ClearSaveStatus : MainScreenEvents
}

View File

@@ -9,11 +9,11 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import org.signal.camera.VideoCaptureResult
import org.signal.camera.VideoOutput
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.signal.camera.VideoCaptureResult
import org.signal.camera.VideoOutput
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
@@ -40,25 +40,25 @@ class MainScreenViewModel : ViewModel() {
}
}
}
fun createVideoOutput(context: Context): VideoOutput {
// Create gallery directory in internal storage
val galleryDir = File(context.filesDir, GALLERY_FOLDER)
if (!galleryDir.exists()) {
galleryDir.mkdirs()
}
// Generate filename with timestamp
val name = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US)
.format(System.currentTimeMillis())
val file = File(galleryDir, "$name.mp4")
// Open the file as a ParcelFileDescriptor
val fileDescriptor = ParcelFileDescriptor.open(
file,
ParcelFileDescriptor.MODE_READ_WRITE or ParcelFileDescriptor.MODE_CREATE
)
return VideoOutput.FileDescriptorOutput(fileDescriptor)
}
@@ -87,7 +87,7 @@ class MainScreenViewModel : ViewModel() {
is VideoCaptureResult.Success -> {
// Close the file descriptor now that recording is complete
result.fileDescriptor?.close()
Log.d(TAG, "Video saved successfully")
_state.value = state.copy(saveStatus = SaveStatus.Success)
}
@@ -97,7 +97,7 @@ class MainScreenViewModel : ViewModel() {
}
}
}
private fun handleClearSaveStatusEvent(
state: MainScreenState,
event: MainScreenEvents.ClearSaveStatus
@@ -111,12 +111,12 @@ class MainScreenViewModel : ViewModel() {
if (!galleryDir.exists()) {
galleryDir.mkdirs()
}
// Generate filename with timestamp
val name = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS", Locale.US)
.format(System.currentTimeMillis())
val file = File(galleryDir, "$name.jpg")
// Save bitmap to file
file.outputStream().use { outputStream ->
event.bitmap.compress(Bitmap.CompressFormat.JPEG, 95, outputStream)

View File

@@ -27,7 +27,6 @@ import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
import androidx.navigation3.runtime.NavBackStack
import org.signal.camera.demo.Screen
import java.io.File
@OptIn(UnstableApi::class)
@Composable
@@ -35,16 +34,16 @@ fun VideoViewerScreen(
backStack: NavBackStack<Screen>
) {
val selectedMedia = org.signal.camera.demo.MediaSelectionHolder.selectedMedia
if (selectedMedia == null || selectedMedia !is org.signal.camera.demo.screens.gallery.MediaItem.Video) {
// No video selected, go back
backStack.removeAt(backStack.lastIndex)
return
}
val context = LocalContext.current
val videoFile = selectedMedia.file
val exoPlayer = remember {
ExoPlayer.Builder(context).build().apply {
val mediaItem = MediaItem.fromUri(videoFile.toURI().toString())
@@ -54,13 +53,13 @@ fun VideoViewerScreen(
repeatMode = Player.REPEAT_MODE_OFF
}
}
DisposableEffect(Unit) {
onDispose {
exoPlayer.release()
}
}
Box(
modifier = Modifier
.fillMaxSize()
@@ -81,7 +80,7 @@ fun VideoViewerScreen(
},
modifier = Modifier.fillMaxSize()
)
// Back button
IconButton(
onClick = { backStack.removeAt(backStack.lastIndex) },

View File

@@ -8,4 +8,4 @@ val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
val Pink40 = Color(0xFF7D5260)

View File

@@ -1,6 +1,5 @@
package org.signal.camera.demo.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
@@ -30,7 +29,7 @@ private val LightColorScheme = lightColorScheme(
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
*/
)
@Composable
@@ -55,4 +54,4 @@ fun CameraXTestTheme(
typography = Typography,
content = content
)
}
}

View File

@@ -30,5 +30,5 @@ val Typography = Typography(
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)
*/
)

View File

@@ -1,9 +1,8 @@
package org.signal.camera.demo
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -14,4 +13,4 @@ class ExampleUnitTest {
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
}

View File

@@ -59,12 +59,15 @@ class RegistrationApplication : Application() {
)
)
CoreUiDependencies.init(this, object : CoreUiDependencies.Provider {
override fun providePackageId(): String = BuildConfig.APPLICATION_ID
override fun provideIsIncognitoKeyboardEnabled(): Boolean = false
override fun provideIsScreenSecurityEnabled(): Boolean = false
override fun provideForceSplitPane(): Boolean = false
})
CoreUiDependencies.init(
this,
object : CoreUiDependencies.Provider {
override fun providePackageId(): String = BuildConfig.APPLICATION_ID
override fun provideIsIncognitoKeyboardEnabled(): Boolean = false
override fun provideIsScreenSecurityEnabled(): Boolean = false
override fun provideForceSplitPane(): Boolean = false
}
)
}
private fun createPushServiceSocket(configuration: SignalServiceConfiguration): PushServiceSocket {

View File

@@ -8,7 +8,6 @@ package org.signal.registration.sample.absbackup
import android.app.backup.BackupAgent
import android.app.backup.BackupDataInput
import android.app.backup.BackupDataOutput
import android.app.backup.FullBackupDataOutput
import android.os.ParcelFileDescriptor
import org.signal.core.util.logging.Log
import org.signal.registration.NetworkController
@@ -17,7 +16,6 @@ import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
@@ -108,4 +106,4 @@ class RegistrationBackupAgent : BackupAgent() {
private val TAG = Log.tag(RegistrationBackupAgent::class)
private const val BACKUP_KEY = "Svr2Credentials"
}
}
}

View File

@@ -10,6 +10,8 @@ import org.signal.core.util.logging.Log
import org.signal.registration.NetworkController
import org.signal.registration.NetworkController.AccountAttributes
import org.signal.registration.NetworkController.BackupMasterKeyError
import org.signal.registration.NetworkController.CheckSvrCredentialsError
import org.signal.registration.NetworkController.CheckSvrCredentialsResponse
import org.signal.registration.NetworkController.CreateSessionError
import org.signal.registration.NetworkController.GetSessionStatusError
import org.signal.registration.NetworkController.GetSvrCredentialsError
@@ -27,8 +29,6 @@ import org.signal.registration.NetworkController.SubmitVerificationCodeError
import org.signal.registration.NetworkController.SvrCredentials
import org.signal.registration.NetworkController.UpdateSessionError
import org.signal.registration.NetworkController.VerificationCodeTransport
import org.signal.registration.NetworkController.CheckSvrCredentialsError
import org.signal.registration.NetworkController.CheckSvrCredentialsResponse
import java.util.Locale
/**

View File

@@ -17,6 +17,8 @@ import org.signal.libsignal.net.Network
import org.signal.libsignal.protocol.util.Hex
import org.signal.registration.NetworkController
import org.signal.registration.NetworkController.AccountAttributes
import org.signal.registration.NetworkController.CheckSvrCredentialsRequest
import org.signal.registration.NetworkController.CheckSvrCredentialsResponse
import org.signal.registration.NetworkController.CreateSessionError
import org.signal.registration.NetworkController.GetSessionStatusError
import org.signal.registration.NetworkController.PreKeyCollection
@@ -25,8 +27,6 @@ import org.signal.registration.NetworkController.RegisterAccountResponse
import org.signal.registration.NetworkController.RegistrationLockResponse
import org.signal.registration.NetworkController.RegistrationNetworkResult
import org.signal.registration.NetworkController.RequestVerificationCodeError
import org.signal.registration.NetworkController.CheckSvrCredentialsRequest
import org.signal.registration.NetworkController.CheckSvrCredentialsResponse
import org.signal.registration.NetworkController.SessionMetadata
import org.signal.registration.NetworkController.SubmitVerificationCodeError
import org.signal.registration.NetworkController.ThirdPartyServiceErrorResponse