diff --git a/.gitignore b/.gitignore
index a070f811..5246cd2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,3 +56,5 @@ fastlane/.env
/app/release/baselineProfiles/1/save-unspecified-release.dm
/app/release/output-metadata.json
/app/src/main/assets/.env
+/.kotlin/sessions/kotlin-compiler-1215430679833621634.salive
+/.kotlin/
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 617f846e..a7143dbf 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -299,6 +299,7 @@ dependencies {
detektPlugins(libs.detekt.rules.authors)
detektPlugins(libs.detekt.rules.libraries)
detektPlugins(libs.detekt.compose)
+ detektPlugins(libs.detekt.rules.compose)
}
configurations.all {
diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml
index 824fccc8..e46e32ce 100644
--- a/app/detekt-baseline.xml
+++ b/app/detekt-baseline.xml
@@ -221,7 +221,6 @@
FinalNewline:BaseComposeActivity.kt$net.opendasharchive.openarchive.features.core.BaseComposeActivity.kt
FinalNewline:BaseDialog.kt$net.opendasharchive.openarchive.features.core.dialog.BaseDialog.kt
FinalNewline:BaseFragment.kt$net.opendasharchive.openarchive.features.core.BaseFragment.kt
- FinalNewline:BaseSnowbirdFragment.kt$net.opendasharchive.openarchive.services.snowbird.BaseSnowbirdFragment.kt
FinalNewline:BaseViewModel.kt$net.opendasharchive.openarchive.util.BaseViewModel.kt
FinalNewline:BasicAuthInterceptor.kt$net.opendasharchive.openarchive.services.webdav.BasicAuthInterceptor.kt
FinalNewline:BiometricAuthenticator.kt$net.opendasharchive.openarchive.features.settings.passcode.BiometricAuthenticator.kt
diff --git a/app/src/main/java/net/opendasharchive/openarchive/features/core/BaseFragment.kt b/app/src/main/java/net/opendasharchive/openarchive/features/core/BaseFragment.kt
index d0949996..18a80906 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/features/core/BaseFragment.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/features/core/BaseFragment.kt
@@ -10,11 +10,11 @@ import net.opendasharchive.openarchive.R
import net.opendasharchive.openarchive.db.SnowbirdError
import net.opendasharchive.openarchive.extensions.androidViewModel
import net.opendasharchive.openarchive.features.core.dialog.DialogStateManager
+import net.opendasharchive.openarchive.features.core.dialog.showDialog
import net.opendasharchive.openarchive.features.onboarding.SpaceSetupActivity
import net.opendasharchive.openarchive.services.snowbird.SnowbirdGroupViewModel
import net.opendasharchive.openarchive.services.snowbird.SnowbirdRepoViewModel
import net.opendasharchive.openarchive.util.FullScreenOverlayManager
-import net.opendasharchive.openarchive.util.Utility
abstract class BaseFragment : Fragment(), ToolbarConfigurable {
@@ -44,10 +44,13 @@ abstract class BaseFragment : Fragment(), ToolbarConfigurable {
}
open fun handleError(error: SnowbirdError) {
- Utility.showMaterialWarning(
- requireContext(),
- error.friendlyMessage
- )
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ title = UiText.DynamicString("Oops")
+ message = UiText.DynamicString(error.friendlyMessage)
+ positiveButton {
+ text = UiText.StringResource(R.string.lbl_ok)
+ }
+ }
}
open fun handleLoadingStatus(isLoading: Boolean) {
diff --git a/app/src/main/java/net/opendasharchive/openarchive/features/main/MainActivity.kt b/app/src/main/java/net/opendasharchive/openarchive/features/main/MainActivity.kt
index bb9a18d2..8dd70428 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/features/main/MainActivity.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/features/main/MainActivity.kt
@@ -9,7 +9,6 @@ import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
-import android.provider.MediaStore
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
@@ -19,12 +18,8 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.LinearLayout
import android.widget.PopupWindow
-import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
-import androidx.appcompat.content.res.AppCompatResources
-import androidx.compose.material3.MaterialTheme
-import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.drawerlayout.widget.DrawerLayout
@@ -76,12 +71,10 @@ import net.opendasharchive.openarchive.upload.UploadManagerFragment
import net.opendasharchive.openarchive.upload.UploadService
import net.opendasharchive.openarchive.util.Prefs
import net.opendasharchive.openarchive.util.ProofModeHelper
-import net.opendasharchive.openarchive.util.Utility
import net.opendasharchive.openarchive.util.extensions.Position
import net.opendasharchive.openarchive.util.extensions.cloak
import net.opendasharchive.openarchive.util.extensions.hide
import net.opendasharchive.openarchive.util.extensions.scaleAndTintDrawable
-import net.opendasharchive.openarchive.util.extensions.scaled
import net.opendasharchive.openarchive.util.extensions.show
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -226,10 +219,10 @@ class MainActivity : BaseActivity(), SpaceDrawerAdapterListener, FolderDrawerAda
override fun onStart() {
super.onStart()
- if(Prefs.useProofMode){
+ if (Prefs.useProofMode) {
Prefs.proofModeLocation = true
Prefs.proofModeNetwork = true
- }else{
+ } else {
Prefs.proofModeLocation = false
Prefs.proofModeNetwork = false
}
@@ -334,9 +327,15 @@ class MainActivity : BaseActivity(), SpaceDrawerAdapterListener, FolderDrawerAda
if (Picker.canPickFiles(this@MainActivity)) {
setAddButtonLongClickEnabled()
onAddLongClick = {
- val addMediaBottomSheet =
- ContentPickerFragment { actionType -> addClicked(actionType) }
- addMediaBottomSheet.show(supportFragmentManager, ContentPickerFragment.TAG)
+ if (Space.current == null) {
+ navigateToAddServer()
+ } else if (getSelectedProject() == null) {
+ navigateToAddFolder()
+ } else {
+ val addMediaBottomSheet =
+ ContentPickerFragment { actionType -> addClicked(actionType) }
+ addMediaBottomSheet.show(supportFragmentManager, ContentPickerFragment.TAG)
+ }
}
supportFragmentManager.setFragmentResultListener(
AddMediaDialogFragment.RESP_TAKE_PHOTO, this@MainActivity
@@ -763,7 +762,7 @@ class MainActivity : BaseActivity(), SpaceDrawerAdapterListener, FolderDrawerAda
getSelectedProject() != null -> {
if (Prefs.addMediaHint) {
when (mediaType) {
- AddMediaType.CAMERA -> Picker.takePhoto(this, mediaLaunchers.cameraLauncher)
+ AddMediaType.CAMERA -> Picker.takePhoto(this@MainActivity, mediaLaunchers.cameraLauncher)
AddMediaType.GALLERY -> Picker.pickMedia(
this,
mediaLaunchers.imagePickerLauncher
@@ -778,6 +777,7 @@ class MainActivity : BaseActivity(), SpaceDrawerAdapterListener, FolderDrawerAda
message = R.string.press_and_hold_options_media_screen_message.asUiText(),
onDone = {
Prefs.addMediaHint = true
+ addClicked(mediaType)
}
)
}
@@ -831,7 +831,16 @@ class MainActivity : BaseActivity(), SpaceDrawerAdapterListener, FolderDrawerAda
}
private fun showNotificationPermissionRationale() {
- Utility.showMaterialWarning(this, "Accept!") { Timber.d("thing") }
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ title = UiText.DynamicString("Notification Permission")
+ message = UiText.DynamicString("We need permission to post notifications")
+ positiveButton {
+ text = UiText.DynamicString("Accept")
+ action = {
+ Timber.d("thing")
+ }
+ }
+ }
}
private fun handleIntent(intent: Intent) {
@@ -879,14 +888,8 @@ class MainActivity : BaseActivity(), SpaceDrawerAdapterListener, FolderDrawerAda
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
- 2 -> Picker.pickMedia(this, mediaLaunchers.imagePickerLauncher)
- REQUEST_CAMERA_PERMISSION -> {
- if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- takePhoto() // ✅ Permission granted, retry camera
- } else {
- Toast.makeText(this, "Camera permission denied", Toast.LENGTH_LONG).show()
- }
- }
+ REQUEST_FILE_MEDIA -> Picker.pickMedia(this, mediaLaunchers.imagePickerLauncher)
+ REQUEST_CAMERA_PERMISSION -> Picker.takePhoto(this, mediaLaunchers.cameraLauncher)
}
}
@@ -971,28 +974,9 @@ class MainActivity : BaseActivity(), SpaceDrawerAdapterListener, FolderDrawerAda
}
}
-
- private fun takePhoto() {
- // Check if CAMERA permission is granted
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
- // Request permission
- ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
- return
- }
-
- // If permission is already granted, start the camera intent
- val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
- if (takePictureIntent.resolveActivity(this.packageManager) != null) {
-
- this.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
- } else {
- Toast.makeText(this, "Camera not available", Toast.LENGTH_SHORT).show()
- }
- }
-
companion object {
// Define request codes
- private const val REQUEST_CAMERA_PERMISSION = 100
- private const val REQUEST_IMAGE_CAPTURE = 101
+ const val REQUEST_CAMERA_PERMISSION = 100
+ const val REQUEST_FILE_MEDIA = 101
}
}
diff --git a/app/src/main/java/net/opendasharchive/openarchive/features/media/MediaLaunchers.kt b/app/src/main/java/net/opendasharchive/openarchive/features/media/MediaLaunchers.kt
index 06bfe950..fad0f07b 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/features/media/MediaLaunchers.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/features/media/MediaLaunchers.kt
@@ -1,12 +1,11 @@
package net.opendasharchive.openarchive.features.media
import android.content.Intent
-import android.net.Uri
import androidx.activity.result.ActivityResultLauncher
import com.esafirm.imagepicker.features.ImagePickerLauncher
data class MediaLaunchers(
val imagePickerLauncher: ImagePickerLauncher,
val filePickerLauncher: ActivityResultLauncher,
- val cameraLauncher: ActivityResultLauncher
+ val cameraLauncher: ActivityResultLauncher
)
\ No newline at end of file
diff --git a/app/src/main/java/net/opendasharchive/openarchive/features/media/Picker.kt b/app/src/main/java/net/opendasharchive/openarchive/features/media/Picker.kt
index 537ad9a9..57799828 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/features/media/Picker.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/features/media/Picker.kt
@@ -10,8 +10,10 @@ import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Environment
+import android.provider.MediaStore
import android.view.View
import android.widget.ProgressBar
+import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
@@ -33,6 +35,8 @@ import net.opendasharchive.openarchive.R
import net.opendasharchive.openarchive.core.logger.AppLogger
import net.opendasharchive.openarchive.db.Media
import net.opendasharchive.openarchive.db.Project
+import net.opendasharchive.openarchive.features.main.MainActivity
+import net.opendasharchive.openarchive.features.main.MainActivity.Companion.REQUEST_CAMERA_PERMISSION
import net.opendasharchive.openarchive.util.Utility
import net.opendasharchive.openarchive.util.extensions.makeSnackBar
import org.witness.proofmode.crypto.HashUtils
@@ -81,8 +85,8 @@ object Picker {
}
}
- val cpl = activity.registerForActivityResult(ActivityResultContracts.TakePicture()) { success ->
- if (success) {
+ val cpl = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == AppCompatActivity.RESULT_OK) {
currentPhotoUri?.let { uri ->
val snackbar = showProgressSnackBar(activity, root, activity.getString(R.string.importing_media))
@@ -108,9 +112,11 @@ object Picker {
fun pickMedia(activity: Activity, launcher: ImagePickerLauncher) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- if (needAskForPermission(activity, arrayOf(
- Manifest.permission.READ_MEDIA_IMAGES,
- Manifest.permission.READ_MEDIA_VIDEO))
+ if (needAskForPermission(
+ activity,
+ arrayOf(Manifest.permission.READ_MEDIA_IMAGES, Manifest.permission.READ_MEDIA_VIDEO),
+ MainActivity.REQUEST_FILE_MEDIA
+ )
) {
return
}
@@ -143,7 +149,7 @@ object Picker {
type = "application/*"
}
- private fun needAskForPermission(activity: Activity, permissions: Array): Boolean {
+ private fun needAskForPermission(activity: Activity, permissions: Array, requestCode: Int): Boolean {
var needAsk = false
for (permission in permissions) {
@@ -158,7 +164,7 @@ object Picker {
if (!needAsk) return false
- ActivityCompat.requestPermissions(activity, permissions, 2)
+ ActivityCompat.requestPermissions(activity, permissions, requestCode)
return true
}
@@ -221,16 +227,34 @@ object Picker {
return media
}
- fun takePhoto(context: Context, launcher: ActivityResultLauncher) {
- val file = Utility.getOutputMediaFileByCache(context, "IMG_${System.currentTimeMillis()}.jpg")
+ fun takePhoto(activity: Activity, launcher: ActivityResultLauncher) {
+
+ if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
+ // Request permission
+ ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION)
+ return
+ }
+
+ val file = Utility.getOutputMediaFileByCache(activity, "IMG_${System.currentTimeMillis()}.jpg")
file?.let {
val uri = FileProvider.getUriForFile(
- context, "${context.packageName}.provider",
+ activity, "${activity.packageName}.provider",
it
)
+
currentPhotoUri = uri
- launcher.launch(uri)
+
+ val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {
+ putExtra(MediaStore.EXTRA_OUTPUT, uri)
+ addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) // Ensure permission is granted
+ }
+
+ if (takePictureIntent.resolveActivity(activity.packageManager) != null) {
+ launcher.launch(takePictureIntent)
+ } else {
+ Toast.makeText(activity, "Camera not available", Toast.LENGTH_SHORT).show()
+ }
}
}
diff --git a/app/src/main/java/net/opendasharchive/openarchive/features/media/PreviewActivity.kt b/app/src/main/java/net/opendasharchive/openarchive/features/media/PreviewActivity.kt
index 082d4505..8ede8e0f 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/features/media/PreviewActivity.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/features/media/PreviewActivity.kt
@@ -18,6 +18,7 @@ import net.opendasharchive.openarchive.features.core.asUiImage
import net.opendasharchive.openarchive.features.core.asUiText
import net.opendasharchive.openarchive.features.core.dialog.DialogType
import net.opendasharchive.openarchive.features.core.dialog.showDialog
+import net.opendasharchive.openarchive.features.main.MainActivity
import net.opendasharchive.openarchive.util.Prefs
import net.opendasharchive.openarchive.util.extensions.hide
import net.opendasharchive.openarchive.util.extensions.show
@@ -306,4 +307,17 @@ class PreviewActivity : BaseActivity(), View.OnClickListener, PreviewAdapter.Lis
}
}
+
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ when (requestCode) {
+ MainActivity.REQUEST_FILE_MEDIA -> Picker.pickMedia(this, mediaLaunchers.imagePickerLauncher)
+ MainActivity.REQUEST_CAMERA_PERMISSION -> Picker.takePhoto(this, mediaLaunchers.cameraLauncher)
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/net/opendasharchive/openarchive/features/settings/passcode/passcode_setup/PasscodeSetupActivity.kt b/app/src/main/java/net/opendasharchive/openarchive/features/settings/passcode/passcode_setup/PasscodeSetupActivity.kt
index 62257065..223bccbd 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/features/settings/passcode/passcode_setup/PasscodeSetupActivity.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/features/settings/passcode/passcode_setup/PasscodeSetupActivity.kt
@@ -4,7 +4,7 @@ import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.MenuItem
-import androidx.activity.OnBackPressedCallback
+import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import net.opendasharchive.openarchive.core.presentation.theme.SaveAppTheme
import net.opendasharchive.openarchive.features.core.BaseActivity
@@ -17,19 +17,9 @@ class PasscodeSetupActivity : BaseActivity() {
const val EXTRA_PASSCODE_ENABLED = "passcode_enabled"
}
-// private val onBackPressedCallback = object : OnBackPressedCallback(enabled = true) {
-// override fun handleOnBackPressed() {
-// setResult(RESULT_CANCELED)
-// finish()
-// }
-// }
-
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- //onBackPressedDispatcher.addCallback(onBackPressedCallback)
-
setContent {
SaveAppTheme {
DefaultScaffold(
@@ -37,11 +27,19 @@ class PasscodeSetupActivity : BaseActivity() {
ComposeAppBar(
title = "Lock app with passcode",
onNavigationAction = {
- //onBackPressedCallback.handleOnBackPressed()
+ setResult(RESULT_CANCELED)
+ finish()
}
)
}
) {
+
+ // Handle back press inside Compose
+ BackHandler {
+ setResult(RESULT_CANCELED)
+ finish()
+ }
+
PasscodeSetupScreen(
onPasscodeSet = {
// Passcode successfully set
diff --git a/app/src/main/java/net/opendasharchive/openarchive/features/settings/passcode/passcode_setup/PasscodeSetupScreen.kt b/app/src/main/java/net/opendasharchive/openarchive/features/settings/passcode/passcode_setup/PasscodeSetupScreen.kt
index 42871f47..728c651f 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/features/settings/passcode/passcode_setup/PasscodeSetupScreen.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/features/settings/passcode/passcode_setup/PasscodeSetupScreen.kt
@@ -99,6 +99,7 @@ private fun PasscodeSetupScreenContent(
verticalArrangement = Arrangement.Top,
modifier = Modifier
.fillMaxWidth()
+ .padding(top = 32.dp)
.padding(horizontal = 24.dp)
.padding(bottom = 24.dp)
) {
@@ -116,8 +117,9 @@ private fun PasscodeSetupScreenContent(
Text(
text = "Make sure you remember this pin. If you forget it, you will need to reset the app, and all data will be erased.",
color = MaterialTheme.colorScheme.error,
+ fontSize = 11.sp,
textAlign = TextAlign.Center,
- fontWeight = FontWeight.Light,
+ fontWeight = FontWeight.Medium,
style = MaterialTheme.typography.labelMedium
)
}
diff --git a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/BaseSnowbirdFragment.kt b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/BaseSnowbirdFragment.kt
deleted file mode 100644
index 84c1c73e..00000000
--- a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/BaseSnowbirdFragment.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.opendasharchive.openarchive.services.snowbird
-
-import android.content.Context
-import android.view.View
-import android.view.inputmethod.InputMethodManager
-import androidx.fragment.app.Fragment
-import net.opendasharchive.openarchive.db.SnowbirdError
-import net.opendasharchive.openarchive.extensions.androidViewModel
-import net.opendasharchive.openarchive.util.Utility
-
-open class BaseSnowbirdFragment : Fragment() {
- val snowbirdGroupViewModel: SnowbirdGroupViewModel by androidViewModel()
- val snowbirdRepoViewModel: SnowbirdRepoViewModel by androidViewModel()
-
- open fun dismissKeyboard(view: View) {
- val imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
- imm.hideSoftInputFromWindow(view.windowToken, 0)
- }
-
- open fun handleError(error: SnowbirdError) {
- Utility.showMaterialWarning(
- requireContext(),
- error.friendlyMessage
- )
- }
-
- open fun handleLoadingStatus(isLoading: Boolean) {
- if (isLoading) {
- //FullScreenOverlayManager.show(this@BaseSnowbirdFragment)
- } else {
- //FullScreenOverlayManager.hide()
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdCreateGroupFragment.kt b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdCreateGroupFragment.kt
index ce0fa6bb..83a642da 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdCreateGroupFragment.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdCreateGroupFragment.kt
@@ -4,8 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.core.os.bundleOf
-import androidx.fragment.app.setFragmentResult
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
@@ -16,8 +14,10 @@ import net.opendasharchive.openarchive.db.SnowbirdError
import net.opendasharchive.openarchive.db.SnowbirdGroup
import net.opendasharchive.openarchive.db.SnowbirdRepo
import net.opendasharchive.openarchive.features.core.BaseFragment
+import net.opendasharchive.openarchive.features.core.UiText
+import net.opendasharchive.openarchive.features.core.dialog.DialogType
+import net.opendasharchive.openarchive.features.core.dialog.showDialog
import net.opendasharchive.openarchive.util.FullScreenOverlayCreateGroupManager
-import net.opendasharchive.openarchive.util.Utility
import timber.log.Timber
class SnowbirdCreateGroupFragment: BaseFragment() {
@@ -126,34 +126,25 @@ class SnowbirdCreateGroupFragment: BaseFragment() {
private fun showConfirmation(repo: SnowbirdRepo?) {
val group = SnowbirdGroup.get(repo!!.groupKey)!!
- Utility.showMaterialPrompt(
- requireContext(),
- title = "Raven Group Created",
- message = "Would you like to share your new group with a QR code?",
- positiveButtonText = "Yes",
- negativeButtonText = "No",
- completion = { affirm ->
- if (affirm) {
- if (isJetpackNavigation) {
- val action =
- SnowbirdCreateGroupFragmentDirections.actionFragmentSnowbirdCreateGroupToFragmentSnowbirdShareGroup(
- group.key
- )
- findNavController().navigate(action)
- } else {
- setFragmentResult(
- RESULT_REQUEST_KEY,
- bundleOf(
- RESULT_NAVIGATION_KEY to RESULT_NAVIGATION_VAL_SHARE_SCREEN,
- RESULT_BUNDLE_GROUP_KEY to group.key
- )
- )
- }
- } else {
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Success
+ title = UiText.DynamicString("Raven Group Created")
+ message = UiText.DynamicString("Would you like to share your new group with a QR code?")
+ positiveButton {
+ text = UiText.DynamicString("Yes")
+ action = {
+ val action =
+ SnowbirdCreateGroupFragmentDirections.actionFragmentSnowbirdCreateGroupToFragmentSnowbirdShareGroup(group.key)
+ findNavController().navigate(action)
+ }
+ }
+ neutralButton {
+ text = UiText.DynamicString("No")
+ action = {
parentFragmentManager.popBackStack()
}
}
- )
+ }
}
override fun getToolbarTitle(): String {
diff --git a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdFileListFragment.kt b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdFileListFragment.kt
index 3096c750..e769d0b1 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdFileListFragment.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdFileListFragment.kt
@@ -22,8 +22,10 @@ import net.opendasharchive.openarchive.db.SnowbirdError
import net.opendasharchive.openarchive.db.SnowbirdFileItem
import net.opendasharchive.openarchive.extensions.androidViewModel
import net.opendasharchive.openarchive.features.core.BaseFragment
+import net.opendasharchive.openarchive.features.core.UiText
+import net.opendasharchive.openarchive.features.core.dialog.DialogType
+import net.opendasharchive.openarchive.features.core.dialog.showDialog
import net.opendasharchive.openarchive.util.SpacingItemDecoration
-import net.opendasharchive.openarchive.util.Utility
import timber.log.Timber
class SnowbirdFileListFragment : BaseFragment() {
@@ -136,16 +138,20 @@ class SnowbirdFileListFragment : BaseFragment() {
private fun onClick(item: SnowbirdFileItem) {
// if (!item.isDownloaded) {
- Utility.showMaterialPrompt(
- requireContext(),
- title = "Download Media?",
- message = "Are you sure you want to download this media?",
- positiveButtonText = "Yes",
- negativeButtonText = "No") { affirm ->
- if (affirm) {
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Warning
+ title = UiText.DynamicString("Download Media?")
+ message = UiText.DynamicString("Are you sure you want to download this media?")
+ positiveButton {
+ text = UiText.DynamicString("Yes")
+ action = {
snowbirdFileViewModel.downloadFile(groupKey, repoKey, item.name)
}
}
+ neutralButton {
+ text = UiText.DynamicString("No")
+ }
+ }
// }
}
@@ -188,10 +194,14 @@ class SnowbirdFileListFragment : BaseFragment() {
private fun onFileDownloaded(uri: Uri) {
handleLoadingStatus(false)
Timber.d("File successfully downloaded: $uri")
- Utility.showMaterialMessage(
- requireContext(),
- title = "Success",
- message = "File successfully downloaded")
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Success
+ title = UiText.StringResource(R.string.label_success_title)
+ message = UiText.DynamicString("File successfully downloaded")
+ positiveButton {
+ text = UiText.StringResource(R.string.label_got_it)
+ }
+ }
}
private fun onFileUploaded(result: FileUploadResult) {
diff --git a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdFragment.kt b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdFragment.kt
index 213eba33..cc1c5cb2 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdFragment.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdFragment.kt
@@ -13,12 +13,15 @@ import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import com.google.zxing.integration.android.IntentIntegrator
import kotlinx.coroutines.launch
+import net.opendasharchive.openarchive.R
import net.opendasharchive.openarchive.databinding.FragmentSnowbirdBinding
import net.opendasharchive.openarchive.db.SnowbirdGroup
import net.opendasharchive.openarchive.extensions.getQueryParameter
-import net.opendasharchive.openarchive.features.main.QRScannerActivity
import net.opendasharchive.openarchive.features.core.BaseFragment
-import net.opendasharchive.openarchive.util.Utility
+import net.opendasharchive.openarchive.features.core.UiText
+import net.opendasharchive.openarchive.features.core.dialog.DialogType
+import net.opendasharchive.openarchive.features.core.dialog.showDialog
+import net.opendasharchive.openarchive.features.main.QRScannerActivity
import timber.log.Timber
class SnowbirdFragment : BaseFragment() {
@@ -127,18 +130,26 @@ class SnowbirdFragment : BaseFragment() {
val name = uriString.getQueryParameter("name")
if (name == null) {
- Utility.showMaterialWarning(
- requireContext(),
- "Unable to determine group name from QR code."
- )
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Warning
+ title = UiText.DynamicString("Oops!")
+ message = UiText.DynamicString("Unable to determine group name from QR code.")
+ positiveButton {
+ text = UiText.StringResource(R.string.lbl_ok)
+ }
+ }
return
}
if (SnowbirdGroup.exists(name)) {
- Utility.showMaterialWarning(
- requireContext(),
- "You have already joined this group."
- )
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Warning
+ title = UiText.DynamicString("Oops!")
+ message = UiText.DynamicString("You have already joined this group.")
+ positiveButton {
+ text = UiText.StringResource(R.string.lbl_ok)
+ }
+ }
return
}
diff --git a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdGroupListFragment.kt b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdGroupListFragment.kt
index 1a0f1440..530bd150 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdGroupListFragment.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdGroupListFragment.kt
@@ -22,8 +22,10 @@ import net.opendasharchive.openarchive.databinding.FragmentSnowbirdGroupListBind
import net.opendasharchive.openarchive.db.SnowbirdError
import net.opendasharchive.openarchive.db.SnowbirdGroup
import net.opendasharchive.openarchive.features.core.BaseFragment
+import net.opendasharchive.openarchive.features.core.UiText
+import net.opendasharchive.openarchive.features.core.dialog.DialogType
+import net.opendasharchive.openarchive.features.core.dialog.showDialog
import net.opendasharchive.openarchive.util.SpacingItemDecoration
-import net.opendasharchive.openarchive.util.Utility
import timber.log.Timber
class SnowbirdGroupListFragment : BaseFragment() {
@@ -126,27 +128,19 @@ class SnowbirdGroupListFragment : BaseFragment() {
private fun onLongPress(groupKey: String) {
AppLogger.d("Long press!")
- Utility.showMaterialPrompt(
- requireContext(),
- title = "Share Group",
- message = "Would you like to share this group?",
- positiveButtonText = "Yes",
- negativeButtonText = "No"
- ) { affirm ->
- if (affirm) {
- if (isJetpackNavigation) {
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Info
+ title = UiText.DynamicString("Share Group")
+ message = UiText.DynamicString("Would you like to share this group?")
+ positiveButton {
+ text = UiText.DynamicString("Yes")
+ action = {
val action = SnowbirdGroupListFragmentDirections.actionFragmentSnowbirdGroupListToFragmentSnowbirdShareGroup(groupKey)
findNavController().navigate(action)
- } else {
- setFragmentResult(
- RESULT_REQUEST_KEY,
- bundleOf(
- RESULT_BUNDLE_NAVIGATION_KEY to RESULT_VAL_RAVEN_SHARE_SCREEN,
- RESULT_BUNDLE_GROUP_KEY to groupKey
- )
- )
}
- //findNavController().navigate(SnowbirdGroupListFragmentDirections.navigateToSnowbirdShareScreen(groupKey))
+ }
+ neutralButton {
+ text = UiText.DynamicString("No")
}
}
}
diff --git a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdJoinGroupFragment.kt b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdJoinGroupFragment.kt
index 95414362..ab1d9388 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdJoinGroupFragment.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdJoinGroupFragment.kt
@@ -8,6 +8,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.launch
+import net.opendasharchive.openarchive.R
import net.opendasharchive.openarchive.databinding.FragmentSnowbirdJoinGroupBinding
import net.opendasharchive.openarchive.db.SnowbirdError
import net.opendasharchive.openarchive.db.SnowbirdGroup
@@ -15,8 +16,10 @@ import net.opendasharchive.openarchive.db.SnowbirdRepo
import net.opendasharchive.openarchive.extensions.getQueryParameter
import net.opendasharchive.openarchive.extensions.showKeyboard
import net.opendasharchive.openarchive.features.core.BaseFragment
+import net.opendasharchive.openarchive.features.core.UiText
+import net.opendasharchive.openarchive.features.core.dialog.DialogType
+import net.opendasharchive.openarchive.features.core.dialog.showDialog
import net.opendasharchive.openarchive.util.FullScreenOverlayCreateGroupManager
-import net.opendasharchive.openarchive.util.Utility
import timber.log.Timber
class SnowbirdJoinGroupFragment: BaseFragment() {
@@ -115,12 +118,16 @@ class SnowbirdJoinGroupFragment: BaseFragment() {
repo.save()
handleCreateGroupLoadingStatus(false)
snowbirdRepoViewModel.fetchRepos(groupKey, false)
- Utility.showMaterialMessage(
- requireContext(),
- title = "Success!",
- // message = "Successfully joined"
- ) {
- parentFragmentManager.popBackStack()
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Success
+ title = UiText.StringResource(R.string.label_success_title)
+ message = UiText.DynamicString("Successfully joined")
+ positiveButton {
+ text = UiText.StringResource(R.string.label_got_it)
+ action = {
+ parentFragmentManager.popBackStack()
+ }
+ }
}
}
diff --git a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdRepoListFragment.kt b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdRepoListFragment.kt
index e3e129b1..14a62d2b 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdRepoListFragment.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/services/snowbird/SnowbirdRepoListFragment.kt
@@ -22,8 +22,10 @@ import net.opendasharchive.openarchive.databinding.FragmentSnowbirdListReposBind
import net.opendasharchive.openarchive.db.SnowbirdError
import net.opendasharchive.openarchive.db.SnowbirdRepo
import net.opendasharchive.openarchive.features.core.BaseFragment
+import net.opendasharchive.openarchive.features.core.UiText
+import net.opendasharchive.openarchive.features.core.dialog.DialogType
+import net.opendasharchive.openarchive.features.core.dialog.showDialog
import net.opendasharchive.openarchive.util.SpacingItemDecoration
-import net.opendasharchive.openarchive.util.Utility
import timber.log.Timber
class SnowbirdRepoListFragment: BaseFragment() {
@@ -96,11 +98,14 @@ class SnowbirdRepoListFragment: BaseFragment() {
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.action_add -> {
- Utility.showMaterialWarning(
- context = requireContext(),
- message = "Feature not implemented yet.",
- positiveButtonText = "OK"
- )
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Warning
+ title = UiText.DynamicString("Oops!")
+ message = UiText.DynamicString("Feature not implemented yet.")
+ positiveButton {
+ text = UiText.StringResource(R.string.lbl_ok)
+ }
+ }
true
}
@@ -154,11 +159,17 @@ class SnowbirdRepoListFragment: BaseFragment() {
adapter.submitList(repos)
if (isRefresh && repos.isEmpty()) {
- Utility.showMaterialMessage(
- requireContext(),
- title = "Info",
- message = "No new repositories found."
- )
+ dialogManager.showDialog(dialogManager.requireResourceProvider()) {
+ type = DialogType.Info
+ title = UiText.StringResource(R.string.label_info_title)
+ message = UiText.DynamicString("No new repositories found.")
+ positiveButton {
+ text = UiText.StringResource(R.string.label_got_it)
+ action = {
+ parentFragmentManager.popBackStack()
+ }
+ }
+ }
}
}
diff --git a/app/src/main/java/net/opendasharchive/openarchive/util/CustomSwitchPreference.kt b/app/src/main/java/net/opendasharchive/openarchive/util/CustomSwitchPreference.kt
index 8f28f791..d089874f 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/util/CustomSwitchPreference.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/util/CustomSwitchPreference.kt
@@ -15,7 +15,7 @@ class CustomSwitchPreference @JvmOverloads constructor(
super.onBindViewHolder(holder)
// Find the switch inside the custom layout
- val switchView = holder.findViewById(R.id.checkbox) as? MaterialSwitch
+ val switchView = holder.findViewById(android.R.id.checkbox) as? MaterialSwitch
switchView?.apply {
isChecked = this@CustomSwitchPreference.isChecked
diff --git a/app/src/main/java/net/opendasharchive/openarchive/util/Utility.kt b/app/src/main/java/net/opendasharchive/openarchive/util/Utility.kt
index 8182ca5d..08daa679 100644
--- a/app/src/main/java/net/opendasharchive/openarchive/util/Utility.kt
+++ b/app/src/main/java/net/opendasharchive/openarchive/util/Utility.kt
@@ -118,22 +118,6 @@ object Utility {
context.startActivity(i)
}
- fun showMaterialWarning(context: Context, message: String? = null, positiveButtonText: String = "Ok", completion: (() -> Unit)? = null) {
- showMaterialMessage(context, "Oops", message, positiveButtonText, completion)
- }
-
- fun showMaterialMessage(context: Context, title: String = "Oops", message: String? = null, positiveButtonText: String = "Ok", completion: (() -> Unit)? = null) {
- Handler(Looper.getMainLooper()).post {
- MaterialAlertDialogBuilder(context)
- .setTitle(title)
- .setMessage(message)
- .setPositiveButton(positiveButtonText) { _, _ ->
- completion?.invoke()
- }
- .show()
- }
- }
-
fun showMaterialPrompt(
context: Context,
title: String,
diff --git a/app/src/main/jniLibs/arm64-v8a/libsave.so b/app/src/main/jniLibs/arm64-v8a/libsave.so
index 092820b3..9947fa51 100755
Binary files a/app/src/main/jniLibs/arm64-v8a/libsave.so and b/app/src/main/jniLibs/arm64-v8a/libsave.so differ
diff --git a/app/src/main/jniLibs/armeabi-v7a/libsave.so b/app/src/main/jniLibs/armeabi-v7a/libsave.so
index 3129b936..9635dd84 100755
Binary files a/app/src/main/jniLibs/armeabi-v7a/libsave.so and b/app/src/main/jniLibs/armeabi-v7a/libsave.so differ
diff --git a/app/src/main/res/drawable/onboarding_archive_png.png b/app/src/main/res/drawable/onboarding_archive_png.png
index c7a99be9..776df485 100644
Binary files a/app/src/main/res/drawable/onboarding_archive_png.png and b/app/src/main/res/drawable/onboarding_archive_png.png differ
diff --git a/app/src/main/res/drawable/onboarding_encrypt_png.png b/app/src/main/res/drawable/onboarding_encrypt_png.png
index d7adfe3d..04360637 100644
Binary files a/app/src/main/res/drawable/onboarding_encrypt_png.png and b/app/src/main/res/drawable/onboarding_encrypt_png.png differ
diff --git a/app/src/main/res/drawable/onboarding_secure_png.png b/app/src/main/res/drawable/onboarding_secure_png.png
index 1927732f..7064a11f 100644
Binary files a/app/src/main/res/drawable/onboarding_secure_png.png and b/app/src/main/res/drawable/onboarding_secure_png.png differ
diff --git a/app/src/main/res/drawable/onboarding_verify_png.png b/app/src/main/res/drawable/onboarding_verify_png.png
index 31e3d33a..f4c8f5e0 100644
Binary files a/app/src/main/res/drawable/onboarding_verify_png.png and b/app/src/main/res/drawable/onboarding_verify_png.png differ
diff --git a/app/src/test/java/net/opendasharchive/openarchive/MainMediaAdapterTest.kt b/app/src/test/java/net/opendasharchive/openarchive/MainMediaAdapterTest.kt
index 9600621a..f0f1b524 100644
--- a/app/src/test/java/net/opendasharchive/openarchive/MainMediaAdapterTest.kt
+++ b/app/src/test/java/net/opendasharchive/openarchive/MainMediaAdapterTest.kt
@@ -91,6 +91,8 @@ class MainMediaAdapterTest {
mediaList,
recyclerView,
checkSelecting = { },
+ allowMultiProjectSelection = TODO(),
+ onDeleteClick = TODO(),
)
}
diff --git a/build.gradle.kts b/build.gradle.kts
index 27898215..c0598d5a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,9 +1,9 @@
plugins {
- id("com.android.application") version "8.3.2" apply false
- id("org.jetbrains.kotlin.android") version "2.1.10" apply false
- id("org.jetbrains.kotlin.plugin.compose") version "2.1.10" apply false
- id("org.jetbrains.kotlin.plugin.serialization") version "2.1.10" apply false
- id("com.google.devtools.ksp") version "2.1.10-1.0.30" apply false
+ id("com.android.application") version "8.9.0" apply false
+ id("org.jetbrains.kotlin.android") version "2.1.20-RC2" apply false
+ id("org.jetbrains.kotlin.plugin.compose") version "2.1.20-RC2" apply false
+ id("org.jetbrains.kotlin.plugin.serialization") version "2.1.20-RC2" apply false
+ id("com.google.devtools.ksp") version "2.1.20-RC2-1.0.31" apply false
id("androidx.navigation.safeargs") version "2.8.8" apply false
diff --git a/config/detekt-config.yml b/config/detekt-config.yml
index a99959f9..a2ddec12 100644
--- a/config/detekt-config.yml
+++ b/config/detekt-config.yml
@@ -14,6 +14,30 @@ config:
# when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
excludes: ''
+compose:
+ ReusedModifierInstance:
+ active: true
+ UnnecessaryEventHandlerParameter:
+ active: true
+ ComposableEventParameterNaming:
+ active: true
+ ComposableParametersOrdering:
+ active: true
+ ModifierHeightWithText:
+ active: true
+ MissingModifierDefaultValue:
+ active: true
+ PublicComposablePreview:
+ active: true
+ TopLevelComposableFunctions:
+ active: true
+ allowInObjects: false
+ ComposableFunctionName:
+ active: true
+ ConditionCouldBeLifted:
+ active: true
+ ignoreCallsWithArgumentNames: [ 'modifier', 'contentAlignment' ]
+
processors:
active: true
exclude:
@@ -644,7 +668,7 @@ style:
maxChainedCalls: 5
MaxLineLength:
active: true
- maxLineLength: 120
+ maxLineLength: 180
excludePackageStatements: true
excludeImportStatements: true
excludeCommentStatements: false
diff --git a/gradle.properties b/gradle.properties
index a4059be7..aed45c8f 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -22,3 +22,4 @@ android.enableJetifier=true
android.nonTransitiveRClass=true
android.nonFinalResIds=true
+org.gradle.configuration-cache=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index ffaeef1e..d1413b2d 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,12 +1,14 @@
[versions]
detekt="1.23.8"
detekt-compose="0.4.22"
+detekt-rules-compose="1.4.0"
[libraries]
detekt-formatting = { group = "io.gitlab.arturbosch.detekt", name = "detekt-formatting", version.ref = "detekt" }
detekt-rules-libraries = { group = "io.gitlab.arturbosch.detekt", name = "detekt-rules-libraries", version.ref = "detekt" }
detekt-rules-authors = { group = "io.gitlab.arturbosch.detekt", name = "detekt-rules-ruleauthors", version.ref = "detekt" }
detekt-compose = { group = "io.nlopez.compose.rules", name = "detekt", version.ref = "detekt-compose" }
+detekt-rules-compose = { module = "ru.kode:detekt-rules-compose", version.ref = "detekt-rules-compose" }
[plugins]
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 5a016c74..0da8ddc3 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
\ No newline at end of file