diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c15f0f5b6..9e137fb44 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -48,7 +48,7 @@ android { defaultConfig { applicationId = "app.grapheneos.camera" minSdk = 29 - targetSdk = 34 + targetSdk = 35 versionCode = 75 versionName = versionCode.toString() resourceConfigurations.add("en") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 94558d31c..e6f770750 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,6 +29,7 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/Theme.App" + android:enableOnBackInvokedCallback="true" tools:ignore="UnusedAttribute"> @@ -38,7 +39,8 @@ android:configChanges="orientation|keyboardHidden|screenSize" android:windowSoftInputMode="stateAlwaysHidden|adjustPan" android:screenOrientation="nosensor" - android:exported="true"> + android:exported="true" + android:theme="@style/Theme.Camera"> @@ -71,7 +73,8 @@ android:screenOrientation="nosensor" android:showWhenLocked="true" android:excludeFromRecents="true" - android:exported="true"> + android:exported="true" + android:theme="@style/Theme.Camera"> @@ -159,28 +162,28 @@ () @@ -1517,28 +1519,28 @@ class CamConfig(private val mActivity: MainActivity) { val dialog = builder.create() dialog.setOnShowListener { - val button: Button = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_NEUTRAL) + val button: Button = dialog.getButton(AlertDialog.BUTTON_NEUTRAL) button.setOnClickListener { } } - dialog.show() + dialog.showIgnoringShortEdgeMode() } fun onStorageLocationNotFound() { // Reverting back to DEFAULT_MEDIA_STORE_CAPTURE_PATH storageLocation = SettingValues.Default.STORAGE_LOCATION - val builder = AlertDialog.Builder(mActivity) - builder.setTitle(R.string.folder_not_found) - builder.setMessage(R.string.reverting_to_default_folder) - builder.setPositiveButton(R.string.ok, null) - builder.setNeutralButton(R.string.more_settings) { _, _ -> - MoreSettings.start(mActivity) - } - val alertDialog: AlertDialog = builder.create() + val builder = MaterialAlertDialogBuilder(mActivity) + .setTitle(R.string.folder_not_found) + .setMessage(R.string.reverting_to_default_folder) + .setPositiveButton(R.string.ok, null) + .setNeutralButton(R.string.more_settings) { _, _ -> + MoreSettings.start(mActivity) + } + val alertDialog = builder.create() alertDialog.setCancelable(false) - alertDialog.show() + alertDialog.showIgnoringShortEdgeMode() } } diff --git a/app/src/main/java/app/grapheneos/camera/capturer/ImageCapturer.kt b/app/src/main/java/app/grapheneos/camera/capturer/ImageCapturer.kt index 791acbda7..4ee56b80d 100644 --- a/app/src/main/java/app/grapheneos/camera/capturer/ImageCapturer.kt +++ b/app/src/main/java/app/grapheneos/camera/capturer/ImageCapturer.kt @@ -1,7 +1,6 @@ package app.grapheneos.camera.capturer import android.annotation.SuppressLint -import android.app.AlertDialog import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager @@ -22,7 +21,9 @@ import app.grapheneos.camera.CapturedItem import app.grapheneos.camera.R import app.grapheneos.camera.ui.activities.MainActivity import app.grapheneos.camera.ui.activities.SecureMainActivity +import app.grapheneos.camera.ui.showIgnoringShortEdgeMode import app.grapheneos.camera.util.printStackTraceToString +import com.google.android.material.dialog.MaterialAlertDialogBuilder private const val imageFileFormat = ".jpg" var isTakingPicture: Boolean = false @@ -196,7 +197,7 @@ class ImageCapturer(val mActivity: MainActivity) { private fun showErrorDialog(message: String, exception: Throwable) { val ctx = mActivity - AlertDialog.Builder(ctx).apply { + MaterialAlertDialogBuilder(ctx).apply { setMessage(message) setPositiveButton(R.string.show_details) { _, _ -> val pkgName = ctx.packageName @@ -205,7 +206,7 @@ class ImageCapturer(val mActivity: MainActivity) { "\npackage: $pkgName:$pkgVersion" + "\n\n${exception.printStackTraceToString()}" - AlertDialog.Builder(ctx).apply { + MaterialAlertDialogBuilder(ctx).apply { setItems(text.lines().toTypedArray(), null) setNeutralButton(R.string.copy_to_clipboard) { _, _ -> val clipData = ClipData.newPlainText(exception.javaClass.name, text) @@ -213,10 +214,10 @@ class ImageCapturer(val mActivity: MainActivity) { cm.setPrimaryClip(clipData) ctx.showMessage(R.string.copied_text_to_clipboard) } - show() + showIgnoringShortEdgeMode() } } - show() + showIgnoringShortEdgeMode() } } diff --git a/app/src/main/java/app/grapheneos/camera/ui/DialogUtil.kt b/app/src/main/java/app/grapheneos/camera/ui/DialogUtil.kt new file mode 100644 index 000000000..572133669 --- /dev/null +++ b/app/src/main/java/app/grapheneos/camera/ui/DialogUtil.kt @@ -0,0 +1,27 @@ +package app.grapheneos.camera.ui + +import android.view.WindowManager +import androidx.appcompat.app.AlertDialog +import com.google.android.material.dialog.MaterialAlertDialogBuilder + +/** + * When in an activity where the status bar is hidden, the window layoutInDisplayCutoutMode + * is set to [WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES], and a + * material alert dialog is present that is large enough, the layout of the dialog will appear + * broken and sometimes will shift randomly. These extensions force the dialog window to ignore + * the short edges mode so that it will appear as normal. + */ + +fun AlertDialog.ignoreShortEdges() { + window?.attributes?.layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT +} + +fun AlertDialog.showIgnoringShortEdgeMode(): AlertDialog { + ignoreShortEdges() + show() + return this +} + +fun MaterialAlertDialogBuilder.showIgnoringShortEdgeMode(): AlertDialog = + this.create().showIgnoringShortEdgeMode() diff --git a/app/src/main/java/app/grapheneos/camera/ui/SettingsDialog.kt b/app/src/main/java/app/grapheneos/camera/ui/SettingsDialog.kt index be8649c47..6a310ee71 100644 --- a/app/src/main/java/app/grapheneos/camera/ui/SettingsDialog.kt +++ b/app/src/main/java/app/grapheneos/camera/ui/SettingsDialog.kt @@ -3,7 +3,9 @@ package app.grapheneos.camera.ui import android.Manifest import android.animation.ArgbEvaluator import android.animation.ValueAnimator +import android.annotation.SuppressLint import android.app.Dialog +import android.content.Context import android.content.pm.PackageManager import android.graphics.Color import android.os.Handler @@ -22,13 +24,11 @@ import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.ImageView import android.widget.LinearLayout -import android.widget.RadioButton import android.widget.RadioGroup import android.widget.ScrollView import android.widget.Spinner import android.widget.ToggleButton import androidx.annotation.StringRes -import androidx.appcompat.widget.SwitchCompat import androidx.camera.core.AspectRatio import androidx.camera.core.CameraSelector import androidx.camera.core.DynamicRange @@ -36,15 +36,22 @@ import androidx.camera.core.ImageCapture import androidx.camera.video.Quality import androidx.camera.video.Recorder import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import androidx.core.graphics.ColorUtils import app.grapheneos.camera.CamConfig import app.grapheneos.camera.R import app.grapheneos.camera.databinding.SettingsBinding import app.grapheneos.camera.ui.activities.MainActivity import app.grapheneos.camera.ui.activities.MoreSettings +import com.google.android.material.color.MaterialColors +import com.google.android.material.materialswitch.MaterialSwitch +import com.google.android.material.radiobutton.MaterialRadioButton import java.util.Collections +import kotlin.math.max -class SettingsDialog(val mActivity: MainActivity) : - Dialog(mActivity, R.style.Theme_App) { +@SuppressLint("ClickableViewAccessibility") +class SettingsDialog(val mActivity: MainActivity, themedContext: Context) : + Dialog(themedContext) { val camConfig = mActivity.camConfig private val binding: SettingsBinding by lazy { SettingsBinding.inflate(layoutInflater) } @@ -63,13 +70,13 @@ class SettingsDialog(val mActivity: MainActivity) : var mScrollViewContent: View var cmRadioGroup: RadioGroup - var qRadio: RadioButton - var lRadio: RadioButton + var qRadio: MaterialRadioButton + var lRadio: MaterialRadioButton - var includeAudioToggle: SwitchCompat - var enableEISToggle: SwitchCompat + var includeAudioToggle: MaterialSwitch + var enableEISToggle: MaterialSwitch - var selfIlluminationToggle: SwitchCompat + var selfIlluminationToggle: MaterialSwitch private val timeOptions = mActivity.resources.getStringArray(R.array.time_options) @@ -83,7 +90,8 @@ class SettingsDialog(val mActivity: MainActivity) : private var moreSettingsButton: View - private val bgBlue = mActivity.getColor(R.color.selected_option_bg) + private val tabSelectedColor = + MaterialColors.getColor(binding.root, com.google.android.material.R.attr.colorPrimary) private fun getString(@StringRes id: Int) = mActivity.getString(id) @@ -248,8 +256,13 @@ class SettingsDialog(val mActivity: MainActivity) : } selfIlluminationToggle = binding.selfIlluminationSwitch - selfIlluminationToggle.setOnClickListener { - camConfig.selfIlluminate = selfIlluminationToggle.isChecked + selfIlluminationToggle.setOnCheckedChangeListener { _, isChecked -> + camConfig.selfIlluminate = isChecked + } + binding.selfIlluminationSwitchContainer.setOnTouchListener { _, event -> + event.setLocation(0f, 0f) + selfIlluminationToggle.dispatchTouchEvent(event) + true } focusTimeoutSpinner = binding.focusTimeoutSpinner @@ -323,7 +336,7 @@ class SettingsDialog(val mActivity: MainActivity) : timerSetting = binding.timerSetting includeAudioToggle = binding.includeAudioSwitch - includeAudioToggle.setOnClickListener { + includeAudioToggle.setOnCheckedChangeListener { _, _ -> if (mActivity.videoCapturer.isRecording) { if (ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { @@ -333,13 +346,13 @@ class SettingsDialog(val mActivity: MainActivity) : // Ensure the option is visually off includeAudioToggle.isChecked = false - return@setOnClickListener + return@setOnCheckedChangeListener } if (!mActivity.videoCapturer.includeAudio) { mActivity.showMessage("Enabling audio while recording is not currently supported when it was disabled at the start") includeAudioToggle.isChecked = false - return@setOnClickListener + return@setOnCheckedChangeListener } if (includeAudioToggle.isChecked) { @@ -357,19 +370,41 @@ class SettingsDialog(val mActivity: MainActivity) : camConfig.includeAudio = includeAudioToggle.isChecked } + binding.includeAudioSwitchContainer.setOnTouchListener { _, event -> + event.setLocation(0f, 0f) + includeAudioToggle.dispatchTouchEvent(event) + true + } enableEISToggle = binding.enableEisSwitch - enableEISToggle.setOnClickListener { - camConfig.enableEIS = enableEISToggle.isChecked - } - enableEISToggle.setOnCheckedChangeListener { _, _ -> + enableEISToggle.setOnCheckedChangeListener { _, isChecked -> + camConfig.enableEIS = isChecked camConfig.startCamera(true) } + binding.enableEisSwitchContainer.setOnTouchListener { _, event -> + event.setLocation(0f, 0f) + enableEISToggle.dispatchTouchEvent(event) + true + } + window?.attributes?.layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT window?.setFlags( WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE ) + + var backgroundColor = ContextCompat.getColor(context, android.R.color.black) + backgroundColor = ColorUtils.setAlphaComponent(backgroundColor, 150) + val settingsDialogBackgroundDrawable = + ContextCompat.getDrawable(context, R.drawable.settings_bg) + settingsDialogBackgroundDrawable?.setTint(backgroundColor) + binding.settingsDialog.background = settingsDialogBackgroundDrawable + + val moreSettingsBackgroundDrawable = + ContextCompat.getDrawable(context, R.drawable.settings_bg) + moreSettingsBackgroundDrawable?.setTint(backgroundColor) + binding.moreSettings.background = moreSettingsBackgroundDrawable } private fun resize() { @@ -379,14 +414,26 @@ class SettingsDialog(val mActivity: MainActivity) : mScrollViewContent.viewTreeObserver.removeOnGlobalLayoutListener(this) - val sdHM = - mActivity.resources.getDimension(R.dimen.settings_dialog_horizontal_margin) - - val sH = (mScrollViewContent.width - (sdHM * 8)).toInt() - + val settingsDialogHorizontalMargin = + mActivity.resources.getDimensionPixelSize(R.dimen.settings_dialog_horizontal_margin) + val moreSettingsButtonTopPadding = + (8 * mActivity.resources.displayMetrics.density).toInt() + val totalDialogHeight = moreSettingsButton.height + moreSettingsButtonTopPadding + + dialog.height + val availableWidth = dialog.width - (settingsDialogHorizontalMargin * 4) + val availableHeight = availableWidth - (totalDialogHeight - mScrollView.height) + + val height = if (mScrollViewContent.height < mScrollView.height) { + mScrollViewContent.height + } else { + max( + mScrollView.height.coerceAtMost(availableHeight), + mScrollViewContent.height.coerceAtMost(availableHeight), + ) + } val lp = LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, - sH.coerceAtMost(mScrollViewContent.height) + height, ) mScrollView.layoutParams = lp @@ -495,27 +542,38 @@ class SettingsDialog(val mActivity: MainActivity) : mActivity.previewView.setBackgroundColor(color) mActivity.rootView.setBackgroundColor(color) mActivity.bottomOverlay.setBackgroundColor(color) - window?.statusBarColor = color } val colorAnimation2 = ValueAnimator.ofObject(ArgbEvaluator(), Color.WHITE, Color.BLACK) colorAnimation2.duration = 300 + + val selectedTextColor = + MaterialColors.getColor(binding.root, com.google.android.material.R.attr.colorOnPrimary) + val colorAnimation3 = ValueAnimator.ofObject(ArgbEvaluator(), selectedTextColor, Color.WHITE) + colorAnimation3.duration = 300 + + var currentUnselectedColor = Color.WHITE colorAnimation2.addUpdateListener { animator -> + currentUnselectedColor = animator.animatedValue as Int + } + colorAnimation3.addUpdateListener { animator -> mActivity.tabLayout.setTabTextColors( - animator.animatedValue as Int, - Color.WHITE + currentUnselectedColor, + animator.animatedValue as Int ) } - val colorAnimation3 = ValueAnimator.ofObject(ArgbEvaluator(), bgBlue, Color.BLACK) - colorAnimation3.duration = 300 - colorAnimation3.addUpdateListener { animator -> + val colorAnimation4 = + ValueAnimator.ofObject(ArgbEvaluator(), tabSelectedColor, Color.BLACK) + colorAnimation4.duration = 300 + colorAnimation4.addUpdateListener { animator -> mActivity.tabLayout.setSelectedTabIndicatorColor(animator.animatedValue as Int) } colorAnimation1.start() colorAnimation2.start() colorAnimation3.start() + colorAnimation4.start() setBrightness(1f) @@ -531,27 +589,37 @@ class SettingsDialog(val mActivity: MainActivity) : mActivity.previewView.setBackgroundColor(color) mActivity.rootView.setBackgroundColor(color) mActivity.bottomOverlay.setBackgroundColor(color) - window?.statusBarColor = color } val colorAnimation2 = ValueAnimator.ofObject(ArgbEvaluator(), Color.BLACK, Color.WHITE) colorAnimation2.duration = 300 + + val selectedTextColor = + MaterialColors.getColor(binding.root, com.google.android.material.R.attr.colorOnPrimary) + val colorAnimation3 = ValueAnimator.ofObject(ArgbEvaluator(), Color.WHITE, selectedTextColor) + colorAnimation3.duration = 300 + + var currentUnselectedTextColor = Color.BLACK colorAnimation2.addUpdateListener { animator -> + currentUnselectedTextColor = animator.animatedValue as Int + } + colorAnimation3.addUpdateListener { animator -> mActivity.tabLayout.setTabTextColors( - animator.animatedValue as Int, - Color.WHITE + currentUnselectedTextColor, + animator.animatedValue as Int ) } - val colorAnimation3 = ValueAnimator.ofObject(ArgbEvaluator(), Color.BLACK, bgBlue) - colorAnimation3.duration = 300 - colorAnimation3.addUpdateListener { animator -> + val colorAnimation4 = ValueAnimator.ofObject(ArgbEvaluator(), Color.BLACK, tabSelectedColor) + colorAnimation4.duration = 300 + colorAnimation4.addUpdateListener { animator -> mActivity.tabLayout.setSelectedTabIndicatorColor(animator.animatedValue as Int) } colorAnimation1.start() colorAnimation2.start() colorAnimation3.start() + colorAnimation4.start() setBrightness(getSystemBrightness()) } @@ -594,7 +662,7 @@ class SettingsDialog(val mActivity: MainActivity) : object : Animation.AnimationListener { override fun onAnimationStart(p0: Animation?) { - moreSettingsButton.visibility = View.GONE + moreSettingsButton.visibility = View.INVISIBLE } override fun onAnimationEnd(p0: Animation?) { diff --git a/app/src/main/java/app/grapheneos/camera/ui/ZoomableImageView.kt b/app/src/main/java/app/grapheneos/camera/ui/ZoomableImageView.kt index b28280f57..cfe4077d4 100644 --- a/app/src/main/java/app/grapheneos/camera/ui/ZoomableImageView.kt +++ b/app/src/main/java/app/grapheneos/camera/ui/ZoomableImageView.kt @@ -154,7 +154,7 @@ class ZoomableImageView @JvmOverloads constructor( } private fun onSingleClick() { - gActivity.toggleActionBarState() + gActivity.toggleUIState() } private fun onDoubleClick(event: MotionEvent) { @@ -249,7 +249,7 @@ class ZoomableImageView @JvmOverloads constructor( scaleAnimator?.cancel() if (isZoomingDisabled) { - gActivity.showActionBar() + gActivity.showUI() } else { gActivity.gallerySlider.isUserInputEnabled = false } @@ -280,7 +280,7 @@ class ZoomableImageView @JvmOverloads constructor( isInZoomMode = true gActivity.let { - it.hideActionBar() + it.hideUI() it.gallerySlider.isUserInputEnabled = false } } @@ -291,7 +291,7 @@ class ZoomableImageView @JvmOverloads constructor( isInZoomMode = false - gActivity.showActionBar() + gActivity.showUI() gActivity.vibrateDevice() } diff --git a/app/src/main/java/app/grapheneos/camera/ui/activities/InAppGallery.kt b/app/src/main/java/app/grapheneos/camera/ui/activities/InAppGallery.kt index 76f9b501c..3be8e5e5a 100644 --- a/app/src/main/java/app/grapheneos/camera/ui/activities/InAppGallery.kt +++ b/app/src/main/java/app/grapheneos/camera/ui/activities/InAppGallery.kt @@ -3,7 +3,6 @@ package app.grapheneos.camera.ui.activities import android.animation.ArgbEvaluator import android.animation.ValueAnimator import android.annotation.SuppressLint -import android.app.AlertDialog import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent @@ -11,7 +10,6 @@ import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.media.MediaMetadataRetriever import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.Handler import android.os.VibrationEffect @@ -24,10 +22,16 @@ import android.util.Log import android.view.Menu import android.view.MenuItem import android.view.View +import android.widget.RelativeLayout import android.widget.Toast +import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.os.BundleCompat +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.viewpager2.widget.ViewPager2 import androidxc.exifinterface.media.ExifInterface import app.grapheneos.camera.CapturedItem @@ -40,6 +44,7 @@ import app.grapheneos.camera.databinding.GalleryBinding import app.grapheneos.camera.util.getParcelableArrayListExtra import app.grapheneos.camera.util.getParcelableExtra import app.grapheneos.camera.util.storageLocationToUiString +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import java.text.SimpleDateFormat import java.util.Date @@ -67,6 +72,8 @@ class InAppGallery : AppCompatActivity() { private var lastViewedMediaItem : CapturedItem? = null + private lateinit var windowInsetsController: WindowInsetsControllerCompat + companion object { const val INTENT_KEY_SECURE_MODE = "is_secure_mode" const val INTENT_KEY_VIDEO_ONLY_MODE = "video_only_mode" @@ -203,7 +210,7 @@ class InAppGallery : AppCompatActivity() { private fun deleteCurrentMedia() { val curItem = getCurrentItem() - AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Dialog_Alert) + MaterialAlertDialogBuilder(this) .setTitle(R.string.delete_title) .setMessage(getString(R.string.delete_description, curItem.uiName())) .setPositiveButton(R.string.delete) { _, _ -> @@ -293,10 +300,8 @@ class InAppGallery : AppCompatActivity() { } - val alertDialog: AlertDialog.Builder = - AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Dialog_Alert) - - alertDialog.setTitle(getString(R.string.file_details)) + val alertDialog = MaterialAlertDialogBuilder(this) + .setTitle(getString(R.string.file_details)) val detailsBuilder = StringBuilder() @@ -389,6 +394,28 @@ class InAppGallery : AppCompatActivity() { bgColorAnim.start() } + private fun animateShadeToTransparent() { + if (binding.shade.alpha == 0f) { + return + } + + binding.shade.animate().apply { + duration = 300 + alpha(0f) + } + } + + private fun animateShadeToOriginal() { + if (binding.shade.alpha == 1f) { + return + } + + binding.shade.animate().apply { + duration = 300 + alpha(1f) + } + } + private fun shareCurrentMedia() { if (isSecureMode) { showMessage(getString(R.string.sharing_not_allowed)) @@ -409,6 +436,12 @@ class InAppGallery : AppCompatActivity() { isSecureMode = intent.getBooleanExtra(INTENT_KEY_SECURE_MODE, false) super.onCreate(savedInstanceState) + enableEdgeToEdge() + windowInsetsController = WindowCompat.getInsetsController(window, window.decorView).apply { + isAppearanceLightStatusBars = false + isAppearanceLightNavigationBars = false + show(WindowInsetsCompat.Type.systemBars()) + } if (isSecureMode) { setShowWhenLocked(true) @@ -420,7 +453,6 @@ class InAppGallery : AppCompatActivity() { setContentView(binding.root) supportActionBar?.let { - it.setBackgroundDrawable(ColorDrawable(ContextCompat.getColor(this, R.color.appbar))) it.setDisplayShowTitleEnabled(false) it.setDisplayHomeAsUpEnabled(true) } @@ -428,13 +460,20 @@ class InAppGallery : AppCompatActivity() { rootView = binding.rootView rootView.setOnClickListener { if (gallerySliderAdapter != null) { - toggleActionBarState() + toggleUIState() } } gallerySlider = binding.gallerySlider - snackBar = Snackbar.make(gallerySlider, "", Snackbar.LENGTH_LONG) + snackBar = Snackbar.make(binding.snackbarAnchor, "", Snackbar.LENGTH_LONG) gallerySlider.setPageTransformer(GSlideTransformer()) + ViewCompat.setOnApplyWindowInsetsListener(binding.snackbarAnchor) { view, insets -> + val systemBars = + insets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.systemBars()) + view.y = -systemBars.bottom.toFloat() + snackBar.setAnchorView(view) + insets + } if (savedInstanceState != null) { lastViewedMediaItem = BundleCompat.getParcelable(savedInstanceState, LAST_VIEWED_ITEM_KEY, CapturedItem::class.java) @@ -493,10 +532,27 @@ class InAppGallery : AppCompatActivity() { binding.placeholderText.root.visibility = View.VISIBLE } }, 500) - - hideActionBar() } } + + supportActionBar?.setBackgroundDrawable(null) + + ViewCompat.setOnApplyWindowInsetsListener(binding.shade) { view, insets -> + val systemBars = insets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.systemBars()) + val actionBarHeight = resources.getDimensionPixelSize(R.dimen.action_bar_height) + view.layoutParams = + RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, + systemBars.top + actionBarHeight + ) + view.background = ContextCompat.getDrawable(this@InAppGallery, R.drawable.shade) + insets + } + } + + override fun onResume() { + super.onResume() + showUI() } fun asyncResultReady(items: ArrayList) { @@ -546,31 +602,35 @@ class InAppGallery : AppCompatActivity() { existingAdapter.notifyItemRangeInserted(1, items.size - 1) } gallerySlider.setCurrentItem(capturedItemPosition, false) - showActionBar() + showUI() } - fun toggleActionBarState() { + fun toggleUIState() { supportActionBar?.let { if (it.isShowing) { - hideActionBar() + hideUI() } else { - showActionBar() + showUI() } } } - fun showActionBar() { + fun showUI() { supportActionBar?.let { it.show() animateBackgroundToOriginal() } + animateShadeToOriginal() + windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) } - fun hideActionBar() { + fun hideUI() { supportActionBar?.let { it.hide() animateBackgroundToBlack() } + animateShadeToTransparent() + windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) } override fun onDestroy() { @@ -581,7 +641,7 @@ class InAppGallery : AppCompatActivity() { fun vibrateDevice() { val vibrator = getSystemService(Vibrator::class.java) - vibrator?.vibrate(VibrationEffect.createOneShot(50, 10)) + vibrator?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK)) } fun showMessage(msg: String) { diff --git a/app/src/main/java/app/grapheneos/camera/ui/activities/MainActivity.kt b/app/src/main/java/app/grapheneos/camera/ui/activities/MainActivity.kt index d94c01d4f..0465e1d29 100644 --- a/app/src/main/java/app/grapheneos/camera/ui/activities/MainActivity.kt +++ b/app/src/main/java/app/grapheneos/camera/ui/activities/MainActivity.kt @@ -3,7 +3,6 @@ package app.grapheneos.camera.ui.activities import android.Manifest import android.animation.Animator import android.annotation.SuppressLint -import android.app.AlertDialog import android.app.Dialog import android.content.ClipData import android.content.ClipboardManager @@ -11,7 +10,6 @@ import android.content.Context import android.content.DialogInterface import android.content.Intent import android.content.pm.PackageManager -import android.database.ContentObserver import android.graphics.Bitmap import android.graphics.ImageDecoder import android.graphics.Point @@ -51,6 +49,7 @@ import android.widget.TextView import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions import androidx.annotation.StringRes +import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.camera.core.FocusMeteringAction import androidx.camera.core.MeteringPointFactory @@ -89,11 +88,14 @@ import app.grapheneos.camera.ui.QRToggle import app.grapheneos.camera.ui.SettingsDialog import app.grapheneos.camera.ui.seekbar.ExposureBar import app.grapheneos.camera.ui.seekbar.ZoomBar +import app.grapheneos.camera.ui.showIgnoringShortEdgeMode import app.grapheneos.camera.util.CameraControl import app.grapheneos.camera.util.ImageResizer import app.grapheneos.camera.util.executeIfAlive import app.grapheneos.camera.util.resolveActivity import app.grapheneos.camera.util.setBlurBitmapCompat +import com.google.android.material.color.DynamicColors +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayout @@ -203,6 +205,8 @@ open class MainActivity : AppCompatActivity(), private lateinit var gLeftDash: View private lateinit var gRightDash: View + private var bottomNavigationBarPadding: Int = 0 + val thumbnailLoaderExecutor = Executors.newSingleThreadExecutor() private val runnable = Runnable { @@ -305,10 +309,9 @@ open class MainActivity : AppCompatActivity(), } private fun showAudioPermissionDeniedDialog(onDisableAudio: () -> Unit = {}) { - val builder = - AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Dialog_Alert) - builder.setTitle(R.string.audio_permission_dialog_title) - builder.setMessage(R.string.audio_permission_dialog_message) + val builder = MaterialAlertDialogBuilder(this) + .setTitle(R.string.audio_permission_dialog_title) + .setMessage(R.string.audio_permission_dialog_message) // Open the settings menu for the current app builder.setPositiveButton(R.string.settings) { _: DialogInterface?, _: Int -> @@ -327,7 +330,7 @@ open class MainActivity : AppCompatActivity(), onDisableAudio() } - audioPermissionDialog = builder.show() + audioPermissionDialog = builder.showIgnoringShortEdgeMode() } fun updateLastFrame() { @@ -446,10 +449,9 @@ open class MainActivity : AppCompatActivity(), // Don't build and show a new dialog if it's already visible if (cameraPermissionDialog != null && cameraPermissionDialog!!.isShowing) return - val builder = - AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Dialog_Alert) - builder.setTitle(R.string.camera_permission_dialog_title) - builder.setMessage(R.string.camera_permission_dialog_message) + val builder = MaterialAlertDialogBuilder(this) + .setTitle(R.string.camera_permission_dialog_title) + .setMessage(R.string.camera_permission_dialog_message) val positiveClicked = AtomicBoolean(false) // Open the settings menu for the current app @@ -473,7 +475,7 @@ open class MainActivity : AppCompatActivity(), finish() } } - cameraPermissionDialog = builder.show() + cameraPermissionDialog = builder.showIgnoringShortEdgeMode() } // Request for the permission (Android will actually popup the permission @@ -906,12 +908,16 @@ open class MainActivity : AppCompatActivity(), insets.left, 0, insets.right, - insets.bottom, + 0, ) it } + zoomBarPanel.setPadding(0, 0, 0, insets.bottom) + exposureBarPanel.setPadding(0, 0, 0, insets.bottom) + bottomNavigationBarPadding = insets.bottom + if (insets.top != 0 && !isInsetSet) { mainFrame.layoutParams = (mainFrame.layoutParams as ViewGroup.MarginLayoutParams).let { @@ -960,7 +966,8 @@ open class MainActivity : AppCompatActivity(), cbText = binding.captureButtonText cbCross = binding.captureButtonCross - settingsDialog = SettingsDialog(this) + val themedContext = DynamicColors.wrapContextIfAvailable(this, R.style.Theme_SettingsDialog) + settingsDialog = SettingsDialog(this, themedContext) SystemSettingsObserver(lifecycle,Settings.System.ACCELEROMETER_ROTATION,this) { forceUpdateOrientationSensor() @@ -1045,7 +1052,7 @@ open class MainActivity : AppCompatActivity(), if (extraHeight169 > 0) { extraHeight169 } else { - it.bottomMargin + bottomNavigationBarPadding } ) @@ -1088,8 +1095,6 @@ open class MainActivity : AppCompatActivity(), } } - private lateinit var dialog: Dialog - open fun bytesToHex(bytes: ByteArray): String { if (bytes.isEmpty()) return "" // outLen will be wrong for empty inputs @@ -1137,10 +1142,9 @@ open class MainActivity : AppCompatActivity(), ) runOnUiThread { - dialog = Dialog(this, R.style.Theme_Dialog) - dialog.requestWindowFeature(Window.FEATURE_NO_TITLE) + val builder = MaterialAlertDialogBuilder(this) val dialogBinding = ScanResultDialogBinding.inflate(layoutInflater) - dialog.setContentView(dialogBinding.root) + builder.setView(dialogBinding.root) val tabLayout: TabLayout = dialogBinding.encodingTabs val textView = dialogBinding.scanResultText @@ -1212,14 +1216,14 @@ open class MainActivity : AppCompatActivity(), ) } - dialog.setOnDismissListener { + builder.setOnDismissListener { isQRDialogShowing = false camConfig.startCamera(true) } camConfig.cameraProvider?.unbindAll() - dialog.show() + builder.showIgnoringShortEdgeMode() } } @@ -1596,7 +1600,7 @@ open class MainActivity : AppCompatActivity(), gLeftDash.setBackgroundResource(R.drawable.white_shadow_rect) gRightDash.setBackgroundResource(R.drawable.white_shadow_rect) - gAngleTextView.setTextColor(ContextCompat.getColor(this, R.color.white)) + gAngleTextView.setTextColor(ContextCompat.getColor(this, android.R.color.white)) } val zOffset = (lzAngle / 60) * dp32 @@ -1636,10 +1640,9 @@ open class MainActivity : AppCompatActivity(), } } - // Vibrates the device for 100 milliseconds. private fun vibrateDevice() { val vibrator = getSystemService(Vibrator::class.java) - vibrator?.vibrate(VibrationEffect.createOneShot(50, 10)) + vibrator?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK)) } override fun onDestroy() { @@ -1681,7 +1684,7 @@ open class MainActivity : AppCompatActivity(), ) && ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.ACCESS_COARSE_LOCATION ) -> { - AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Dialog_Alert).let { + MaterialAlertDialogBuilder(this).let { it.setTitle(R.string.location_permission_dialog_title) it.setMessage(R.string.location_permission_dialog_message) @@ -1701,7 +1704,7 @@ open class MainActivity : AppCompatActivity(), camConfig.requireLocation = false } } - }.show() + }.showIgnoringShortEdgeMode() } (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) diff --git a/app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt b/app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt index 163a74ffd..18b228fbf 100644 --- a/app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt +++ b/app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt @@ -10,18 +10,22 @@ import android.view.MotionEvent import android.view.View import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager +import android.widget.Button import android.widget.EditText -import android.widget.ImageView import android.widget.TextView +import androidx.activity.enableEdgeToEdge import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.OnApplyWindowInsetsListener +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import app.grapheneos.camera.CamConfig import app.grapheneos.camera.CapturedItems import app.grapheneos.camera.NumInputFilter import app.grapheneos.camera.R import app.grapheneos.camera.databinding.MoreSettingsBinding import app.grapheneos.camera.util.storageLocationToUiString +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener { @@ -32,7 +36,7 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener { private lateinit var sLField: EditText - private lateinit var rSLocation: ImageView + private lateinit var rSLocation: Button private lateinit var rootView: View @@ -71,6 +75,7 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + enableEdgeToEdge() val camConfig = obtainCamConfig(intent) if (camConfig == null) { @@ -81,9 +86,6 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener { binding = MoreSettingsBinding.inflate(layoutInflater) setContentView(binding.root) - setTitle(R.string.more_settings) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - window.navigationBarColor = Color.TRANSPARENT val showStorageSettings = this !is MoreSettingsSecure @@ -120,7 +122,7 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener { rSLocation = binding.refreshStorageLocation rSLocation.setOnClickListener { - val dialog = AlertDialog.Builder(this) + val dialog = MaterialAlertDialogBuilder(this) dialog.setTitle(R.string.are_you_sure) @@ -237,6 +239,23 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener { if (!showStorageSettings) { binding.storageLocationSettings.visibility = View.GONE } + + binding.appBar.setNavigationOnClickListener { + finish() + } + + ViewCompat.setOnApplyWindowInsetsListener(binding.scrollView) { v, insets -> + val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + val cutouts = insets.getInsets(WindowInsetsCompat.Type.displayCutout()) + v.setPadding(cutouts.left, 0, cutouts.right, systemBars.bottom) + insets + } + + ViewCompat.setOnApplyWindowInsetsListener(binding.appBar) { v, insets -> + val cutouts = insets.getInsets(WindowInsetsCompat.Type.displayCutout()) + v.setPadding(cutouts.left, 0, cutouts.right, 0) + insets + } } override fun dispatchTouchEvent(event: MotionEvent): Boolean { diff --git a/app/src/main/java/app/grapheneos/camera/ui/activities/VideoPlayer.kt b/app/src/main/java/app/grapheneos/camera/ui/activities/VideoPlayer.kt index 11c15428c..bca4ff1a1 100644 --- a/app/src/main/java/app/grapheneos/camera/ui/activities/VideoPlayer.kt +++ b/app/src/main/java/app/grapheneos/camera/ui/activities/VideoPlayer.kt @@ -6,9 +6,15 @@ import android.media.MediaMetadataRetriever import android.net.Uri import android.os.Bundle import android.util.Log +import android.widget.FrameLayout import android.widget.MediaController +import android.widget.RelativeLayout +import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat import androidx.lifecycle.Lifecycle import app.grapheneos.camera.R import app.grapheneos.camera.databinding.VideoPlayerBinding @@ -28,6 +34,13 @@ class VideoPlayer : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + enableEdgeToEdge() + + val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) + windowInsetsController.isAppearanceLightStatusBars = false + windowInsetsController.isAppearanceLightNavigationBars = false + windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) + val intent = this.intent if (intent.getBooleanExtra(IN_SECURE_MODE, false)) { setShowWhenLocked(true) @@ -49,15 +62,31 @@ class VideoPlayer : AppCompatActivity() { val mediaController = object : MediaController(this) { override fun show() { super.show() - supportActionBar?.show() + showActionBar() + windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) } override fun hide() { super.hide() - supportActionBar?.hide() + hideActionBar() + windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) } } + supportActionBar?.setBackgroundDrawable(null) + + ViewCompat.setOnApplyWindowInsetsListener(binding.shade) { view, insets -> + val systemBars = insets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.systemBars()) + val actionBarHeight = resources.getDimensionPixelSize(R.dimen.action_bar_height) + view.layoutParams = + FrameLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, + systemBars.top + actionBarHeight + ) + view.background = ContextCompat.getDrawable(this@VideoPlayer, R.drawable.shade) + insets + } + thread { var hasAudio = true try { @@ -86,7 +115,7 @@ class VideoPlayer : AppCompatActivity() { videoView.start() } - supportActionBar?.show() + showActionBar() mediaController.show(0) } @@ -102,6 +131,38 @@ class VideoPlayer : AppCompatActivity() { override fun onResume() { super.onResume() + showActionBar() + } + + private fun hideActionBar() { + supportActionBar?.hide() + animateShadeToTransparent() + } + + private fun showActionBar() { supportActionBar?.show() + animateShadeToOriginal() + } + + private fun animateShadeToTransparent() { + if (binding.shade.alpha == 0f) { + return + } + + binding.shade.animate().apply { + duration = 300 + alpha(0f) + } + } + + private fun animateShadeToOriginal() { + if (binding.shade.alpha == 1f) { + return + } + + binding.shade.animate().apply { + duration = 300 + alpha(1f) + } } } diff --git a/app/src/main/res/drawable/aspect_ratio.xml b/app/src/main/res/drawable/aspect_ratio.xml index 147f3c42b..768477b12 100644 --- a/app/src/main/res/drawable/aspect_ratio.xml +++ b/app/src/main/res/drawable/aspect_ratio.xml @@ -3,7 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> - + diff --git a/app/src/main/res/drawable/back.xml b/app/src/main/res/drawable/back.xml new file mode 100644 index 000000000..f99fea719 --- /dev/null +++ b/app/src/main/res/drawable/back.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/back_white.xml b/app/src/main/res/drawable/back_white.xml new file mode 100644 index 000000000..670b59ebe --- /dev/null +++ b/app/src/main/res/drawable/back_white.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/camera_shutter_normal.xml b/app/src/main/res/drawable/camera_shutter_normal.xml index 666b267fc..35489efdc 100644 --- a/app/src/main/res/drawable/camera_shutter_normal.xml +++ b/app/src/main/res/drawable/camera_shutter_normal.xml @@ -4,7 +4,7 @@ android:shape="oval"> diff --git a/app/src/main/res/drawable/dropdown.xml b/app/src/main/res/drawable/dropdown.xml index 0f42a052e..32519d404 100644 --- a/app/src/main/res/drawable/dropdown.xml +++ b/app/src/main/res/drawable/dropdown.xml @@ -1,4 +1,4 @@ - diff --git a/app/src/main/res/drawable/exposure_neg.xml b/app/src/main/res/drawable/exposure_neg.xml index 15473672e..dbde23dfc 100644 --- a/app/src/main/res/drawable/exposure_neg.xml +++ b/app/src/main/res/drawable/exposure_neg.xml @@ -7,7 +7,7 @@ diff --git a/app/src/main/res/drawable/exposure_plus.xml b/app/src/main/res/drawable/exposure_plus.xml index 90136e96d..aaad104a9 100644 --- a/app/src/main/res/drawable/exposure_plus.xml +++ b/app/src/main/res/drawable/exposure_plus.xml @@ -7,7 +7,7 @@ diff --git a/app/src/main/res/drawable/flash_auto.xml b/app/src/main/res/drawable/flash_auto.xml index f65697266..bbec0b026 100644 --- a/app/src/main/res/drawable/flash_auto.xml +++ b/app/src/main/res/drawable/flash_auto.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/flash_auto_circle.xml b/app/src/main/res/drawable/flash_auto_circle.xml index ff7d1cf2e..2242768a4 100644 --- a/app/src/main/res/drawable/flash_auto_circle.xml +++ b/app/src/main/res/drawable/flash_auto_circle.xml @@ -2,7 +2,7 @@ - + - + diff --git a/app/src/main/res/drawable/flash_off_circle.xml b/app/src/main/res/drawable/flash_off_circle.xml index b7936f2b6..0e1300af9 100644 --- a/app/src/main/res/drawable/flash_off_circle.xml +++ b/app/src/main/res/drawable/flash_off_circle.xml @@ -2,7 +2,7 @@ - + - + diff --git a/app/src/main/res/drawable/flash_on_circle.xml b/app/src/main/res/drawable/flash_on_circle.xml index 7cf1c3b02..590775ff8 100644 --- a/app/src/main/res/drawable/flash_on_circle.xml +++ b/app/src/main/res/drawable/flash_on_circle.xml @@ -2,7 +2,7 @@ - + diff --git a/app/src/main/res/drawable/grid_3x3.xml b/app/src/main/res/drawable/grid_3x3.xml index ba1bd84fe..aba9e643f 100644 --- a/app/src/main/res/drawable/grid_3x3.xml +++ b/app/src/main/res/drawable/grid_3x3.xml @@ -3,6 +3,7 @@ android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" + android:tint="?attr/colorOnPrimary" xmlns:android="http://schemas.android.com/apk/res/android"> - + - + - + diff --git a/app/src/main/res/drawable/grid_off_circle.xml b/app/src/main/res/drawable/grid_off_circle.xml index 5566f87d0..98c97e15d 100644 --- a/app/src/main/res/drawable/grid_off_circle.xml +++ b/app/src/main/res/drawable/grid_off_circle.xml @@ -2,7 +2,7 @@ - + diff --git a/app/src/main/res/drawable/info_adaptable.xml b/app/src/main/res/drawable/info_adaptable.xml index 6a5c448b1..82d83c785 100644 --- a/app/src/main/res/drawable/info_adaptable.xml +++ b/app/src/main/res/drawable/info_adaptable.xml @@ -1,13 +1,12 @@ diff --git a/app/src/main/res/drawable/location.xml b/app/src/main/res/drawable/location.xml index fe627e973..e3446a9a0 100644 --- a/app/src/main/res/drawable/location.xml +++ b/app/src/main/res/drawable/location.xml @@ -4,7 +4,7 @@ - + - + diff --git a/app/src/main/res/drawable/location_on.xml b/app/src/main/res/drawable/location_on.xml index 8128e2d59..a1555821d 100644 --- a/app/src/main/res/drawable/location_on.xml +++ b/app/src/main/res/drawable/location_on.xml @@ -6,7 +6,7 @@ xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/app/src/main/res/drawable/mode_indicator.xml b/app/src/main/res/drawable/mode_indicator.xml index 289ec37de..51187f77b 100644 --- a/app/src/main/res/drawable/mode_indicator.xml +++ b/app/src/main/res/drawable/mode_indicator.xml @@ -4,15 +4,8 @@ - - - - - - + diff --git a/app/src/main/res/drawable/more.xml b/app/src/main/res/drawable/more.xml new file mode 100644 index 000000000..b29b2aef5 --- /dev/null +++ b/app/src/main/res/drawable/more.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/option_circle.xml b/app/src/main/res/drawable/option_circle.xml index 09ea19ed3..f5e289f2c 100644 --- a/app/src/main/res/drawable/option_circle.xml +++ b/app/src/main/res/drawable/option_circle.xml @@ -11,6 +11,6 @@ + android:color="@android:color/white"/> diff --git a/app/src/main/res/drawable/qr_result_background.xml b/app/src/main/res/drawable/qr_result_background.xml index 3fc1cb840..4525b51d6 100644 --- a/app/src/main/res/drawable/qr_result_background.xml +++ b/app/src/main/res/drawable/qr_result_background.xml @@ -1,6 +1,6 @@ - + diff --git a/app/src/main/res/drawable/refresh.xml b/app/src/main/res/drawable/refresh.xml index b064e3c44..6229bd0af 100644 --- a/app/src/main/res/drawable/refresh.xml +++ b/app/src/main/res/drawable/refresh.xml @@ -1,12 +1,11 @@ diff --git a/app/src/main/res/drawable/retake.xml b/app/src/main/res/drawable/retake.xml index d650a69ea..3b9fbd7ad 100644 --- a/app/src/main/res/drawable/retake.xml +++ b/app/src/main/res/drawable/retake.xml @@ -7,8 +7,6 @@ diff --git a/app/src/main/res/drawable/selfie_preview.xml b/app/src/main/res/drawable/selfie_preview.xml index 548644ef6..076b8a5a3 100644 --- a/app/src/main/res/drawable/selfie_preview.xml +++ b/app/src/main/res/drawable/selfie_preview.xml @@ -1,13 +1,12 @@ diff --git a/app/src/main/res/drawable/settings_bg.xml b/app/src/main/res/drawable/settings_bg.xml index 0af17f3c2..8fdf761d7 100644 --- a/app/src/main/res/drawable/settings_bg.xml +++ b/app/src/main/res/drawable/settings_bg.xml @@ -1,8 +1,4 @@ - - - - - - \ No newline at end of file + + + diff --git a/app/src/main/res/drawable/settings_normal.xml b/app/src/main/res/drawable/settings_normal.xml index 7dd89d53a..f7f14f4ab 100644 --- a/app/src/main/res/drawable/settings_normal.xml +++ b/app/src/main/res/drawable/settings_normal.xml @@ -8,7 +8,7 @@ - + diff --git a/app/src/main/res/drawable/settings_pressed.xml b/app/src/main/res/drawable/settings_pressed.xml index 8b06fcc50..f0fae8dd7 100644 --- a/app/src/main/res/drawable/settings_pressed.xml +++ b/app/src/main/res/drawable/settings_pressed.xml @@ -8,7 +8,7 @@ - + diff --git a/app/src/main/res/drawable/shade.xml b/app/src/main/res/drawable/shade.xml new file mode 100644 index 000000000..73f3d75e3 --- /dev/null +++ b/app/src/main/res/drawable/shade.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/drawable/share.xml b/app/src/main/res/drawable/share.xml index ed8423f0d..87fe3479f 100644 --- a/app/src/main/res/drawable/share.xml +++ b/app/src/main/res/drawable/share.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/share_grey.xml b/app/src/main/res/drawable/share_white.xml similarity index 92% rename from app/src/main/res/drawable/share_grey.xml rename to app/src/main/res/drawable/share_white.xml index 13bb17316..88147d8e8 100644 --- a/app/src/main/res/drawable/share_grey.xml +++ b/app/src/main/res/drawable/share_white.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/storage.xml b/app/src/main/res/drawable/storage.xml index fdc32a324..9588f5573 100644 --- a/app/src/main/res/drawable/storage.xml +++ b/app/src/main/res/drawable/storage.xml @@ -1,13 +1,12 @@ diff --git a/app/src/main/res/drawable/straighten.xml b/app/src/main/res/drawable/straighten.xml index 4f72fbff3..e3b4de3a5 100644 --- a/app/src/main/res/drawable/straighten.xml +++ b/app/src/main/res/drawable/straighten.xml @@ -1,13 +1,12 @@ + android:fillColor="?attr/colorControlNormal" + android:pathData="M21,6L3,6c-1.1,0 -2,0.9 -2,2v8c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,8c0,-1.1 -0.9,-2 -2,-2zM21,16L3,16L3,8h2v4h2L7,8h2v4h2L11,8h2v4h2L15,8h2v4h2L19,8h2v8z" /> diff --git a/app/src/main/res/drawable/torch.xml b/app/src/main/res/drawable/torch.xml index 88f7c2597..65f49d77b 100644 --- a/app/src/main/res/drawable/torch.xml +++ b/app/src/main/res/drawable/torch.xml @@ -4,7 +4,7 @@ - + - + + android:fillColor="?attr/colorControlNormal" + android:pathData="M6,14l3,3v7h6v-7l3,-3V9H6V14zM11,1" /> diff --git a/app/src/main/res/drawable/torch_off_button.xml b/app/src/main/res/drawable/torch_off_button.xml index 87d0cb0d4..aa366ee33 100644 --- a/app/src/main/res/drawable/torch_off_button.xml +++ b/app/src/main/res/drawable/torch_off_button.xml @@ -9,17 +9,17 @@ + android:width="4dp" + android:color="@android:color/white" /> + android:width="36dp" + android:height="36dp"/> diff --git a/app/src/main/res/drawable/torch_off_white.xml b/app/src/main/res/drawable/torch_off_white.xml new file mode 100644 index 000000000..a819ee184 --- /dev/null +++ b/app/src/main/res/drawable/torch_off_white.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/torch_on.xml b/app/src/main/res/drawable/torch_on.xml index 7fdbb6000..d5cdddeaa 100644 --- a/app/src/main/res/drawable/torch_on.xml +++ b/app/src/main/res/drawable/torch_on.xml @@ -4,12 +4,11 @@ android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" + android:tint="?attr/colorOnPrimary" xmlns:android="http://schemas.android.com/apk/res/android"> \ No newline at end of file diff --git a/app/src/main/res/drawable/torch_on_button.xml b/app/src/main/res/drawable/torch_on_button.xml index 0b67390c5..ccc4d2431 100644 --- a/app/src/main/res/drawable/torch_on_button.xml +++ b/app/src/main/res/drawable/torch_on_button.xml @@ -8,7 +8,7 @@ @@ -16,9 +16,9 @@ + android:width="36dp" + android:height="36dp"/> diff --git a/app/src/main/res/drawable/torch_on_white.xml b/app/src/main/res/drawable/torch_on_white.xml new file mode 100644 index 000000000..361c8de9c --- /dev/null +++ b/app/src/main/res/drawable/torch_on_white.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/volume_up.xml b/app/src/main/res/drawable/volume_up.xml index c8cec25e7..39f8ca901 100644 --- a/app/src/main/res/drawable/volume_up.xml +++ b/app/src/main/res/drawable/volume_up.xml @@ -1,13 +1,12 @@ diff --git a/app/src/main/res/drawable/white_option_circle.xml b/app/src/main/res/drawable/white_option_circle.xml index 658f26876..1f5978d66 100644 --- a/app/src/main/res/drawable/white_option_circle.xml +++ b/app/src/main/res/drawable/white_option_circle.xml @@ -11,6 +11,6 @@ + android:color="@android:color/white"/> diff --git a/app/src/main/res/drawable/zsl.xml b/app/src/main/res/drawable/zsl.xml index 2b62257c6..d4ada277c 100644 --- a/app/src/main/res/drawable/zsl.xml +++ b/app/src/main/res/drawable/zsl.xml @@ -1,13 +1,12 @@ \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 2c55cf04e..79eb338c0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,13 +5,13 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@android:color/black" tools:context=".ui.activities.MainActivity"> @@ -90,7 +90,7 @@ android:shadowDx="1.5" android:shadowDy="1.3" android:shadowRadius="1.6" - android:textColor="@color/white" + android:textColor="@android:color/white" android:textAlignment="center"/> + android:textColor="@android:color/white"/> + android:layout_marginBottom="4dp" /> diff --git a/app/src/main/res/layout/gallery.xml b/app/src/main/res/layout/gallery.xml index 90a7e7f0b..db514febf 100644 --- a/app/src/main/res/layout/gallery.xml +++ b/app/src/main/res/layout/gallery.xml @@ -2,7 +2,7 @@ @@ -16,4 +16,16 @@ layout="@layout/gallery_placeholder" android:id="@+id/placeholder_text" /> + + + + + diff --git a/app/src/main/res/layout/more_settings.xml b/app/src/main/res/layout/more_settings.xml index 92700b1a0..c3b8117f2 100644 --- a/app/src/main/res/layout/more_settings.xml +++ b/app/src/main/res/layout/more_settings.xml @@ -1,727 +1,726 @@ - - + + + + + + + android:clipToPadding="false" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - - + android:layout_height="match_parent" + android:orientation="vertical"> + + + android:background="?android:attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingTop="8dp" + android:paddingHorizontal="16dp" + android:paddingBottom="10dp"> + + - - - + + + + + + + + + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="0dp" /> - + android:background="?android:attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingTop="8dp" + android:paddingHorizontal="16dp" + android:paddingBottom="10dp"> + + - + - - - + + + - + - - - + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="0dp" /> - - - - - - - - - - + android:layout_height="match_parent" + android:orientation="vertical"> + + + android:background="?android:attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingStart="10dp" + android:paddingTop="8dp" + android:paddingEnd="6dp" + android:paddingBottom="10dp" + android:visibility="gone"> + + - - - + + + + + + + + + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="0dp" /> - + android:background="?android:attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingTop="8dp" + android:paddingHorizontal="16dp" + android:paddingBottom="10dp"> + + - + - - - + + + - + - - - + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="0dp" /> - - - - - - - - + android:background="?android:attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingTop="8dp" + android:paddingHorizontal="16dp" + android:paddingBottom="10dp"> + + - - - + android:layout_marginHorizontal="4dp" + android:layout_weight="1" + android:orientation="vertical"> - + + + - + - + android:layout_height="match_parent" + android:orientation="horizontal"> + android:labelFor="@id/photo_quality_setting" + android:maxLength="3" + android:paddingTop="15dp" + android:textAlignment="center" + android:textSize="16sp" /> - + - + - - - - - - + android:background="?android:attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingTop="8dp" + android:paddingHorizontal="16dp" + android:paddingBottom="10dp"> + + - - - + + + + + + + + + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="0dp" /> - - - - - - - - - - + android:layout_height="match_parent" + android:orientation="vertical"> + + + android:background="?android:attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:orientation="horizontal" + android:paddingTop="8dp" + android:paddingHorizontal="16dp" + android:paddingBottom="10dp"> + + - - - + + + + + + + + + android:layout_gravity="end|center_vertical" + android:layout_marginEnd="0dp" /> - - - - - - - - - - + android:layout_height="match_parent" + android:orientation="vertical"> - + android:layout_marginVertical="12dp" + android:layout_marginStart="78dp" + android:text="@string/storage" /> - + + + + android:layout_marginHorizontal="4dp" + android:layout_weight="1" + android:orientation="vertical"> - + android:layout_marginStart="10dp" + android:text="@string/storage_location" + android:textColor="?android:textColorPrimary" + android:textSize="16sp" /> - + android:orientation="horizontal"> + + + +