Update app and package names
@@ -75,7 +75,8 @@ android {
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
val currentJavaVersionFromLibs = JavaVersion.valueOf(libs.versions.app.build.javaVersion.get().toString())
|
||||
val currentJavaVersionFromLibs =
|
||||
JavaVersion.valueOf(libs.versions.app.build.javaVersion.get())
|
||||
sourceCompatibility = currentJavaVersionFromLibs
|
||||
targetCompatibility = currentJavaVersionFromLibs
|
||||
}
|
||||
@@ -84,7 +85,7 @@ android {
|
||||
kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get()
|
||||
}
|
||||
|
||||
namespace = "com.simplemobiletools.camera"
|
||||
namespace = "org.fossify.camera"
|
||||
|
||||
lint {
|
||||
checkReleaseBuilds = false
|
||||
@@ -99,7 +100,7 @@ detekt {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.simple.tools.commons)
|
||||
implementation(libs.fossify.commons)
|
||||
implementation(libs.bundles.androidx.camera)
|
||||
implementation(libs.androidx.documentfile)
|
||||
implementation(libs.androidx.exifinterface)
|
||||
|
||||
@@ -1,196 +1,359 @@
|
||||
<?xml version="1.0" ?>
|
||||
<SmellBaseline>
|
||||
<ManuallySuppressedIssues></ManuallySuppressedIssues>
|
||||
<CurrentIssues>
|
||||
<ID>ComplexCondition:MainActivity.kt$MainActivity$!mIsHardwareShutterHandled && config.volumeButtonsAsShutter && (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP)</ID>
|
||||
<ID>CyclomaticComplexMethod:CameraXPreview.kt$CameraXPreview$@SuppressLint("MissingPermission", "NewApi") private fun startRecording()</ID>
|
||||
<ID>CyclomaticComplexMethod:ImageSaver.kt$ImageSaver$@SuppressLint("RestrictedApi") private fun saveImageToTempFile(): File?</ID>
|
||||
<ID>CyclomaticComplexMethod:PhotoProcessor.kt$PhotoProcessor$override fun doInBackground(vararg params: ByteArray): String</ID>
|
||||
<ID>EmptyFunctionBlock:FocusCircleView.kt$FocusCircleView${}</ID>
|
||||
<ID>FunctionNaming:ImageUtil.kt$ImageUtil$private fun yuv_420_888toNv21(image: ImageProxy): ByteArray</ID>
|
||||
<ID>ImplicitDefaultLocale:MySize.kt$MySize$String.format("%.1f", (width * height.toFloat()) / ONE_MEGA_PIXEL)</ID>
|
||||
<ID>ImplicitDefaultLocale:VideoQuality.kt$VideoQuality$String.format("%.1f", (width * height.toFloat()) / VideoQuality.ONE_MEGA_PIXEL)</ID>
|
||||
<ID>LargeClass:MainActivity.kt$MainActivity : SimpleActivityMediaSavedListenerCameraXPreviewListener</ID>
|
||||
<ID>LongMethod:ImageSaver.kt$ImageSaver$@SuppressLint("RestrictedApi") private fun saveImageToTempFile(): File?</ID>
|
||||
<ID>LongMethod:PhotoProcessor.kt$PhotoProcessor$override fun doInBackground(vararg params: ByteArray): String</ID>
|
||||
<ID>LongMethod:ShadowDrawable.kt$ShadowDrawable$override fun draw(canvas: Canvas)</ID>
|
||||
<ID>LongParameterList:CameraXInitializer.kt$CameraXInitializer$( previewView: PreviewView, listener: CameraXPreviewListener, mediaSoundHelper: MediaSoundHelper, outputUri: Uri?, isThirdPartyIntent: Boolean, initInPhotoMode: Boolean, )</ID>
|
||||
<ID>LongParameterList:CameraXPreview.kt$CameraXPreview$( private val activity: BaseSimpleActivity, private val previewView: PreviewView, private val mediaSoundHelper: MediaSoundHelper, private val mediaOutputHelper: MediaOutputHelper, private val cameraErrorHandler: CameraErrorHandler, private val listener: CameraXPreviewListener, private val isThirdPartyIntent: Boolean, initInPhotoMode: Boolean, )</ID>
|
||||
<ID>LongParameterList:ImageSaver.kt$ImageSaver$( private val contentResolver: ContentResolver, private val image: ImageProxy, private val mediaOutput: MediaOutput.ImageCaptureOutput, private val metadata: Metadata, private val jpegQuality: Int, private val saveExifAttributes: Boolean, private val onImageSaved: (Uri) -> Unit, private val onError: (ImageCaptureException) -> Unit, )</ID>
|
||||
<ID>LongParameterList:ImageSaver.kt$ImageSaver.Companion$( contentResolver: ContentResolver, image: ImageProxy, mediaOutput: MediaOutput.ImageCaptureOutput, metadata: Metadata, jpegQuality: Int, saveExifAttributes: Boolean, onImageSaved: (Uri) -> Unit, onError: (ImageCaptureException) -> Unit, )</ID>
|
||||
<ID>LoopWithTooManyJumpStatements:ImageQualityManager.kt$ImageQualityManager$for</ID>
|
||||
<ID>LoopWithTooManyJumpStatements:MediaActionSound.kt$MediaActionSound$for</ID>
|
||||
<ID>MagicNumber:BitmapUtils.kt$BitmapUtils$128</ID>
|
||||
<ID>MagicNumber:BitmapUtils.kt$BitmapUtils$7</ID>
|
||||
<ID>MagicNumber:BitmapUtils.kt$BitmapUtils$8</ID>
|
||||
<ID>MagicNumber:CameraXPreview.kt$CameraXPreview.<no name provided>$135</ID>
|
||||
<ID>MagicNumber:CameraXPreview.kt$CameraXPreview.<no name provided>$225</ID>
|
||||
<ID>MagicNumber:CameraXPreview.kt$CameraXPreview.<no name provided>$315</ID>
|
||||
<ID>MagicNumber:CameraXPreview.kt$CameraXPreview.<no name provided>$45</ID>
|
||||
<ID>MagicNumber:Config.kt$Config$80</ID>
|
||||
<ID>MagicNumber:Constants.kt$270</ID>
|
||||
<ID>MagicNumber:Constants.kt$90</ID>
|
||||
<ID>MagicNumber:FocusCircleView.kt$FocusCircleView$500L</ID>
|
||||
<ID>MagicNumber:FocusCircleView.kt$FocusCircleView$50f</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$33</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$35</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$39</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$44</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$46</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$52</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$1000</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$134</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$225</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$289</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$75</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$90</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$1.9f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$16</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$19</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$3</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$3f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$4</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$4f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$5</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$5f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$6</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$8f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$9f</ID>
|
||||
<ID>MagicNumber:PhotoProcessor.kt$PhotoProcessor$360</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$100</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$50</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$55</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$60</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$65</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$70</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$75</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$80</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$85</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$90</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$95</ID>
|
||||
<ID>MagicNumber:ShadowDrawable.kt$ShadowDrawable$255.0f</ID>
|
||||
<ID>MagicNumber:TimerMode.kt$TimerMode.TIMER_10$10000</ID>
|
||||
<ID>MagicNumber:TimerMode.kt$TimerMode.TIMER_3$3000</ID>
|
||||
<ID>MagicNumber:TimerMode.kt$TimerMode.TIMER_5$5000</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$1.9f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$16</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$19</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$3</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$3f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$4</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$4f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$5</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$5f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$6</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$8f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$9f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.FHD$1080</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.FHD$1920</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.HD$1280</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.HD$720</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.SD$480</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.SD$720</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.UHD$2160</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.UHD$3840</ID>
|
||||
<ID>MaxLineLength:BitmapUtils.kt$BitmapUtils$val upperBound = if (minSideLength < 0) 128 else floor(w / minSideLength).coerceAtMost(floor(h / minSideLength)).toInt()</ID>
|
||||
<ID>MaxLineLength:CameraErrorHandler.kt$CameraErrorHandler$VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE -> context.toast(R.string.video_capture_insufficient_storage_error)</ID>
|
||||
<ID>MaxLineLength:CameraXPreview.kt$CameraXPreview$private</ID>
|
||||
<ID>MaxLineLength:CameraXPreview.kt$CameraXPreview$val scaleGesture = camera?.let { ScaleGestureDetector(activity, PinchToZoomOnScaleGestureListener(it.cameraInfo, it.cameraControl)) }</ID>
|
||||
<ID>MaxLineLength:Config.kt$Config$var path = prefs.getString(SAVE_PHOTOS, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString())</ID>
|
||||
<ID>MaxLineLength:ImageQualityManager.kt$ImageQualityManager$val configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue</ID>
|
||||
<ID>MaxLineLength:ImageQualityManager.kt$ImageQualityManager.Companion$private val CAMERA_LENS = arrayOf(CameraCharacteristics.LENS_FACING_FRONT, CameraCharacteristics.LENS_FACING_BACK)</ID>
|
||||
<ID>MaxLineLength:ImageUtil.kt$ImageUtil$require(image.format == ImageFormat.YUV_420_888) { "Incorrect image format of the input image proxy: " + image.format }</ID>
|
||||
<ID>MaxLineLength:ImageUtil.kt$ImageUtil.CodecFailedException$class</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$binding.toggleCamera.setImageResource(if (frontCamera) R.drawable.ic_camera_rear_vector else R.drawable.ic_camera_front_vector)</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$constraintSet.connect(previewView.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$hasPermission(PERMISSION_WRITE_STORAGE) && hasPermission(PERMISSION_CAMERA) && hasPermission(PERMISSION_RECORD_AUDIO)</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$if</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$private</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$private fun isImageCaptureIntent(): Boolean</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$val iconColors = intArrayOf(ContextCompat.getColor(this, com.simplemobiletools.commons.R.color.md_grey_white), primaryColor)</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$val marginBottom = safeInsetBottom + navigationBarHeight + resources.getDimensionPixelSize(com.simplemobiletools.commons.R.dimen.bigger_margin)</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$val uri = if (isPhoto) MediaStore.Images.Media.EXTERNAL_CONTENT_URI else MediaStore.Video.Media.EXTERNAL_CONTENT_URI</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$var hasMediaPermission = hasPermission(PERMISSION_READ_MEDIA_IMAGES) || hasPermission(PERMISSION_READ_MEDIA_VIDEO)</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$}</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity.<no name provided>$override</ID>
|
||||
<ID>MaxLineLength:MediaActionSound.kt$MediaActionSound$else -> Log.e(TAG, "OnLoadCompleteListener() called in wrong state: ${sound.state} for sound: ${sound.mediaSound}")</ID>
|
||||
<ID>MaxLineLength:MediaActionSound.kt$MediaActionSound.Companion$private val SOUNDS = arrayOf(SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, STOP_VIDEO_RECORDING, TIMER_COUNTDOWN, TIMER_COUNTDOWN_2_SECONDS)</ID>
|
||||
<ID>MaxLineLength:MediaOutputHelper.kt$MediaOutputHelper$put(MediaStore.MediaColumns.DATA, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString())</ID>
|
||||
<ID>MaxLineLength:PhotoProcessor.kt$PhotoProcessor$activity.config.savePhotosFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()</ID>
|
||||
<ID>MaxLineLength:PhotoProcessor.kt$PhotoProcessor$document = document?.createFile("", path.substring(path.lastIndexOf('/') + 1)) ?: activity.getDocumentFile(path)</ID>
|
||||
<ID>MaxLineLength:PhotoProcessor.kt$PhotoProcessor$val activity: MainActivity</ID>
|
||||
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$OpenDeviceSettingsDialog(activity = this@SettingsActivity, message = getString(com.simplemobiletools.commons.R.string.allow_location_permission))</ID>
|
||||
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_2_title_commons, com.simplemobiletools.commons.R.string.faq_2_text_commons))</ID>
|
||||
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_6_title_commons, com.simplemobiletools.commons.R.string.faq_6_text_commons))</ID>
|
||||
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)</ID>
|
||||
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$it.beGoneIf(settingsUseEnglishHolder.isGone() && settingsPurchaseThankYouHolder.isGone() && settingsLanguageHolder.isGone())</ID>
|
||||
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())</ID>
|
||||
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$updateMaterialActivityViews(settingsCoordinator, settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)</ID>
|
||||
<ID>MaxLineLength:ShadowDrawable.kt$ShadowDrawable$if</ID>
|
||||
<ID>MaxLineLength:ShadowDrawable.kt$ShadowDrawable$obtainStyledAttributes.getColor(R.styleable.ShadowDrawable_android_shadowColor, ContextCompat.getColor(context, com.simplemobiletools.commons.R.color.md_grey_400_dark))</ID>
|
||||
<ID>MaxLineLength:ShadowDrawable.kt$ShadowDrawable$sharedBitmap = Bitmap.createBitmap(SHARED_BITMAP_BUFFER_SIZE, SHARED_BITMAP_BUFFER_SIZE, Bitmap.Config.ARGB_8888)</ID>
|
||||
<ID>MaxLineLength:ShadowDrawable.kt$ShadowDrawable$val shadowRadius = obtainStyledAttributes.getFloat(R.styleable.ShadowDrawable_android_shadowRadius, 0.0f).coerceAtLeast(0.0f)</ID>
|
||||
<ID>MaxLineLength:VideoQualityManager.kt$VideoQualityManager$val selectionIndex = mediaSizeStore.getCurrentSizeIndex(isPhotoCapture = false, isFrontCamera = isFrontCamera).coerceAtLeast(0)</ID>
|
||||
<ID>NestedBlockDepth:ImageQualityManager.kt$ImageQualityManager$fun initSupportedQualities()</ID>
|
||||
<ID>NestedBlockDepth:ImageSaver.kt$ImageSaver$private fun copyTempFileToDestination(tempFile: File)</ID>
|
||||
<ID>NestedBlockDepth:MediaOutputHelper.kt$MediaOutputHelper$fun getImageMediaOutput(): MediaOutput.ImageCaptureOutput</ID>
|
||||
<ID>NestedBlockDepth:MediaOutputHelper.kt$MediaOutputHelper$fun getVideoMediaOutput(): MediaOutput.VideoCaptureOutput</ID>
|
||||
<ID>NestedBlockDepth:MediaOutputHelper.kt$MediaOutputHelper$private fun getUriForFilePath(path: String): Uri?</ID>
|
||||
<ID>NestedBlockDepth:PhotoProcessor.kt$PhotoProcessor$override fun doInBackground(vararg params: ByteArray): String</ID>
|
||||
<ID>NestedBlockDepth:VideoQualityManager.kt$VideoQualityManager$fun initSupportedQualities(cameraProvider: ProcessCameraProvider)</ID>
|
||||
<ID>ReturnCount:ImageSaver.kt$ImageSaver$@SuppressLint("RestrictedApi") private fun saveImageToTempFile(): File?</ID>
|
||||
<ID>ReturnCount:MediaActionSound.kt$MediaActionSound$private fun loadSound(sound: SoundState): Int</ID>
|
||||
<ID>ReturnCount:MediaOutputHelper.kt$MediaOutputHelper$private fun getFileDescriptorMediaOutput(): MediaOutput.FileDescriptorMediaOutput?</ID>
|
||||
<ID>ReturnCount:MediaOutputHelper.kt$MediaOutputHelper$private fun getUriForFilePath(path: String): Uri?</ID>
|
||||
<ID>ReturnCount:PhotoProcessor.kt$PhotoProcessor$override fun doInBackground(vararg params: ByteArray): String</ID>
|
||||
<ID>ReturnCount:PhotoProcessor.kt$PhotoProcessor$private fun rotate(bitmap: Bitmap, degree: Int): Bitmap?</ID>
|
||||
<ID>SwallowedException:BitmapUtils.kt$BitmapUtils$ex: OutOfMemoryError</ID>
|
||||
<ID>SwallowedException:CameraXPreview.kt$CameraXPreview$e: Exception</ID>
|
||||
<ID>SwallowedException:ImageUtil.kt$ImageUtil$e: IOException</ID>
|
||||
<ID>SwallowedException:MediaOutputHelper.kt$MediaOutputHelper$e: Exception</ID>
|
||||
<ID>SwallowedException:PhotoProcessor.kt$PhotoProcessor$e: Exception</ID>
|
||||
<ID>SwallowedException:PhotoProcessor.kt$PhotoProcessor$e: OutOfMemoryError</ID>
|
||||
<ID>ThrowsCount:ImageUtil.kt$ImageUtil$@Throws(CodecFailedException::class) private fun cropJpegByteArray( data: ByteArray, cropRect: Rect, @IntRange(from = 1, to = 100) jpegQuality: Int, ): ByteArray</ID>
|
||||
<ID>TooGenericExceptionCaught:CameraXPreview.kt$CameraXPreview$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:ImageQualityManager.kt$ImageQualityManager$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:MediaOutputHelper.kt$MediaOutputHelper$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:PhotoProcessor.kt$PhotoProcessor$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:VideoQualityManager.kt$VideoQualityManager$e: Exception</ID>
|
||||
<ID>TooManyFunctions:CameraXPreview.kt$CameraXPreview : MyPreviewDefaultLifecycleObserver</ID>
|
||||
<ID>TooManyFunctions:CameraXPreviewListener.kt$CameraXPreviewListener</ID>
|
||||
<ID>TooManyFunctions:MainActivity.kt$MainActivity : SimpleActivityMediaSavedListenerCameraXPreviewListener</ID>
|
||||
<ID>TooManyFunctions:MediaOutputHelper.kt$MediaOutputHelper</ID>
|
||||
<ID>TooManyFunctions:MySize.kt$MySize</ID>
|
||||
<ID>TooManyFunctions:SettingsActivity.kt$SettingsActivity : SimpleActivity</ID>
|
||||
<ID>TooManyFunctions:ShadowDrawable.kt$ShadowDrawable : Drawable</ID>
|
||||
<ID>TooManyFunctions:VideoQuality.kt$VideoQuality</ID>
|
||||
<ID>UnusedPrivateProperty:ImageUtil.kt$ImageUtil$col</ID>
|
||||
<ID>UnusedPrivateProperty:ImageUtil.kt$ImageUtil$row</ID>
|
||||
<ID>UseCheckOrError:CameraXPreview.kt$CameraXPreview$throw IllegalStateException("Camera initialization failed.")</ID>
|
||||
<ID>UseCheckOrError:MainActivity.kt$MainActivity.<no name provided>$throw IllegalStateException("Unsupported tab position ${tab.position}")</ID>
|
||||
<ID>VariableNaming:FocusCircleView.kt$FocusCircleView$private val CIRCLE_DURATION = 500L</ID>
|
||||
<ID>VariableNaming:FocusCircleView.kt$FocusCircleView$private val CIRCLE_RADIUS = 50f</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import android.view.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import androidx.camera.core.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import androidx.camera.core.ImageCapture.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import androidx.camera.video.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import com.simplemobiletools.camera.extensions.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import com.simplemobiletools.camera.helpers.*</ID>
|
||||
<ID>WildcardImport:ImageSaver.kt$import java.io.*</ID>
|
||||
<ID>WildcardImport:ImageUtil.kt$import android.graphics.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import android.view.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import androidx.core.view.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import androidx.transition.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import com.simplemobiletools.camera.helpers.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import com.simplemobiletools.commons.extensions.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import com.simplemobiletools.commons.helpers.*</ID>
|
||||
<ID>WildcardImport:MediaOutputHelper.kt$import com.simplemobiletools.commons.extensions.*</ID>
|
||||
<ID>WildcardImport:PhotoProcessor.kt$import com.simplemobiletools.commons.extensions.*</ID>
|
||||
<ID>WildcardImport:SettingsActivity.kt$import com.simplemobiletools.commons.dialogs.*</ID>
|
||||
<ID>WildcardImport:SettingsActivity.kt$import com.simplemobiletools.commons.extensions.*</ID>
|
||||
<ID>WildcardImport:SettingsActivity.kt$import com.simplemobiletools.commons.helpers.*</ID>
|
||||
<ID>WildcardImport:ShadowDrawable.kt$import android.graphics.*</ID>
|
||||
</CurrentIssues>
|
||||
<ManuallySuppressedIssues></ManuallySuppressedIssues>
|
||||
<CurrentIssues>
|
||||
<ID>ComplexCondition:MainActivity.kt$MainActivity$!mIsHardwareShutterHandled &&
|
||||
config.volumeButtonsAsShutter && (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
|
||||
keyCode == KeyEvent.KEYCODE_VOLUME_UP)
|
||||
</ID>
|
||||
<ID>
|
||||
CyclomaticComplexMethod:CameraXPreview.kt$CameraXPreview$@SuppressLint("MissingPermission",
|
||||
"NewApi") private fun startRecording()
|
||||
</ID>
|
||||
<ID>CyclomaticComplexMethod:ImageSaver.kt$ImageSaver$@SuppressLint("RestrictedApi") private
|
||||
fun saveImageToTempFile(): File?
|
||||
</ID>
|
||||
<ID>CyclomaticComplexMethod:PhotoProcessor.kt$PhotoProcessor$override fun
|
||||
doInBackground(vararg params: ByteArray): String
|
||||
</ID>
|
||||
<ID>EmptyFunctionBlock:FocusCircleView.kt$FocusCircleView${}</ID>
|
||||
<ID>FunctionNaming:ImageUtil.kt$ImageUtil$private fun yuv_420_888toNv21(image: ImageProxy):
|
||||
ByteArray
|
||||
</ID>
|
||||
<ID>ImplicitDefaultLocale:MySize.kt$MySize$String.format("%.1f", (width * height.toFloat())
|
||||
/ ONE_MEGA_PIXEL)
|
||||
</ID>
|
||||
<ID>ImplicitDefaultLocale:VideoQuality.kt$VideoQuality$String.format("%.1f", (width *
|
||||
height.toFloat()) / VideoQuality.ONE_MEGA_PIXEL)
|
||||
</ID>
|
||||
<ID>LargeClass:MainActivity.kt$MainActivity :
|
||||
SimpleActivityMediaSavedListenerCameraXPreviewListener
|
||||
</ID>
|
||||
<ID>LongMethod:ImageSaver.kt$ImageSaver$@SuppressLint("RestrictedApi") private fun
|
||||
saveImageToTempFile(): File?
|
||||
</ID>
|
||||
<ID>LongMethod:PhotoProcessor.kt$PhotoProcessor$override fun doInBackground(vararg params:
|
||||
ByteArray): String
|
||||
</ID>
|
||||
<ID>LongMethod:ShadowDrawable.kt$ShadowDrawable$override fun draw(canvas: Canvas)</ID>
|
||||
<ID>LongParameterList:CameraXInitializer.kt$CameraXInitializer$( previewView: PreviewView,
|
||||
listener: CameraXPreviewListener, mediaSoundHelper: MediaSoundHelper, outputUri: Uri?,
|
||||
isThirdPartyIntent: Boolean, initInPhotoMode: Boolean, )
|
||||
</ID>
|
||||
<ID>LongParameterList:CameraXPreview.kt$CameraXPreview$( private val activity:
|
||||
BaseSimpleActivity, private val previewView: PreviewView, private val mediaSoundHelper:
|
||||
MediaSoundHelper, private val mediaOutputHelper: MediaOutputHelper, private val
|
||||
cameraErrorHandler: CameraErrorHandler, private val listener: CameraXPreviewListener,
|
||||
private val isThirdPartyIntent: Boolean, initInPhotoMode: Boolean, )
|
||||
</ID>
|
||||
<ID>LongParameterList:ImageSaver.kt$ImageSaver$( private val contentResolver:
|
||||
ContentResolver, private val image: ImageProxy, private val mediaOutput:
|
||||
MediaOutput.ImageCaptureOutput, private val metadata: Metadata, private val jpegQuality:
|
||||
Int, private val saveExifAttributes: Boolean, private val onImageSaved: (Uri) ->
|
||||
Unit, private val onError: (ImageCaptureException) -> Unit, )
|
||||
</ID>
|
||||
<ID>LongParameterList:ImageSaver.kt$ImageSaver.Companion$( contentResolver: ContentResolver,
|
||||
image: ImageProxy, mediaOutput: MediaOutput.ImageCaptureOutput, metadata: Metadata,
|
||||
jpegQuality: Int, saveExifAttributes: Boolean, onImageSaved: (Uri) -> Unit, onError:
|
||||
(ImageCaptureException) -> Unit, )
|
||||
</ID>
|
||||
<ID>LoopWithTooManyJumpStatements:ImageQualityManager.kt$ImageQualityManager$for</ID>
|
||||
<ID>LoopWithTooManyJumpStatements:MediaActionSound.kt$MediaActionSound$for</ID>
|
||||
<ID>MagicNumber:BitmapUtils.kt$BitmapUtils$128</ID>
|
||||
<ID>MagicNumber:BitmapUtils.kt$BitmapUtils$7</ID>
|
||||
<ID>MagicNumber:BitmapUtils.kt$BitmapUtils$8</ID>
|
||||
<ID>MagicNumber:CameraXPreview.kt$CameraXPreview.<no name provided>$135</ID>
|
||||
<ID>MagicNumber:CameraXPreview.kt$CameraXPreview.<no name provided>$225</ID>
|
||||
<ID>MagicNumber:CameraXPreview.kt$CameraXPreview.<no name provided>$315</ID>
|
||||
<ID>MagicNumber:CameraXPreview.kt$CameraXPreview.<no name provided>$45</ID>
|
||||
<ID>MagicNumber:Config.kt$Config$80</ID>
|
||||
<ID>MagicNumber:Constants.kt$270</ID>
|
||||
<ID>MagicNumber:Constants.kt$90</ID>
|
||||
<ID>MagicNumber:FocusCircleView.kt$FocusCircleView$500L</ID>
|
||||
<ID>MagicNumber:FocusCircleView.kt$FocusCircleView$50f</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$33</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$35</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$39</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$44</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$46</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity$52</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$1000</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$134</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$225</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$289</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$75</ID>
|
||||
<ID>MagicNumber:MainActivity.kt$MainActivity.<no name provided>$90</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$1.9f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$16</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$19</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$3</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$3f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$4</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$4f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$5</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$5f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$6</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$8f</ID>
|
||||
<ID>MagicNumber:MySize.kt$MySize$9f</ID>
|
||||
<ID>MagicNumber:PhotoProcessor.kt$PhotoProcessor$360</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$100</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$50</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$55</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$60</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$65</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$70</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$75</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$80</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$85</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$90</ID>
|
||||
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$95</ID>
|
||||
<ID>MagicNumber:ShadowDrawable.kt$ShadowDrawable$255.0f</ID>
|
||||
<ID>MagicNumber:TimerMode.kt$TimerMode.TIMER_10$10000</ID>
|
||||
<ID>MagicNumber:TimerMode.kt$TimerMode.TIMER_3$3000</ID>
|
||||
<ID>MagicNumber:TimerMode.kt$TimerMode.TIMER_5$5000</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$1.9f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$16</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$19</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$3</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$3f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$4</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$4f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$5</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$5f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$6</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$8f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality$9f</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.FHD$1080</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.FHD$1920</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.HD$1280</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.HD$720</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.SD$480</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.SD$720</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.UHD$2160</ID>
|
||||
<ID>MagicNumber:VideoQuality.kt$VideoQuality.UHD$3840</ID>
|
||||
<ID>MaxLineLength:BitmapUtils.kt$BitmapUtils$val upperBound = if (minSideLength < 0) 128
|
||||
else floor(w / minSideLength).coerceAtMost(floor(h / minSideLength)).toInt()
|
||||
</ID>
|
||||
<ID>
|
||||
MaxLineLength:CameraErrorHandler.kt$CameraErrorHandler$VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE
|
||||
-> context.toast(R.string.video_capture_insufficient_storage_error)
|
||||
</ID>
|
||||
<ID>MaxLineLength:CameraXPreview.kt$CameraXPreview$private</ID>
|
||||
<ID>MaxLineLength:CameraXPreview.kt$CameraXPreview$val scaleGesture = camera?.let {
|
||||
ScaleGestureDetector(activity, PinchToZoomOnScaleGestureListener(it.cameraInfo,
|
||||
it.cameraControl)) }
|
||||
</ID>
|
||||
<ID>MaxLineLength:Config.kt$Config$var path = prefs.getString(SAVE_PHOTOS,
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString())
|
||||
</ID>
|
||||
<ID>MaxLineLength:ImageQualityManager.kt$ImageQualityManager$val configMap =
|
||||
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue
|
||||
</ID>
|
||||
<ID>MaxLineLength:ImageQualityManager.kt$ImageQualityManager.Companion$private val
|
||||
CAMERA_LENS = arrayOf(CameraCharacteristics.LENS_FACING_FRONT,
|
||||
CameraCharacteristics.LENS_FACING_BACK)
|
||||
</ID>
|
||||
<ID>MaxLineLength:ImageUtil.kt$ImageUtil$require(image.format == ImageFormat.YUV_420_888) {
|
||||
"Incorrect image format of the input image proxy: " + image.format }
|
||||
</ID>
|
||||
<ID>MaxLineLength:ImageUtil.kt$ImageUtil.CodecFailedException$class</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$binding.toggleCamera.setImageResource(if
|
||||
(frontCamera) R.drawable.ic_camera_rear_vector else R.drawable.ic_camera_front_vector)
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$constraintSet.connect(previewView.id,
|
||||
ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$hasPermission(PERMISSION_WRITE_STORAGE) &&
|
||||
hasPermission(PERMISSION_CAMERA) && hasPermission(PERMISSION_RECORD_AUDIO)
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$if</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$layoutParams =
|
||||
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$private</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$private fun isImageCaptureIntent(): Boolean
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$val iconColors =
|
||||
intArrayOf(ContextCompat.getColor(this, org.fossify.commons.R.color.md_grey_white),
|
||||
primaryColor)
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$val marginBottom = safeInsetBottom +
|
||||
navigationBarHeight +
|
||||
resources.getDimensionPixelSize(org.fossify.commons.R.dimen.bigger_margin)
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$val uri = if (isPhoto)
|
||||
MediaStore.Images.Media.EXTERNAL_CONTENT_URI else
|
||||
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$var hasMediaPermission =
|
||||
hasPermission(PERMISSION_READ_MEDIA_IMAGES) ||
|
||||
hasPermission(PERMISSION_READ_MEDIA_VIDEO)
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$window.decorView.systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity$}</ID>
|
||||
<ID>MaxLineLength:MainActivity.kt$MainActivity.<no name provided>$override</ID>
|
||||
<ID>MaxLineLength:MediaActionSound.kt$MediaActionSound$else -> Log.e(TAG,
|
||||
"OnLoadCompleteListener() called in wrong state: ${sound.state} for sound:
|
||||
${sound.mediaSound}")
|
||||
</ID>
|
||||
<ID>MaxLineLength:MediaActionSound.kt$MediaActionSound.Companion$private val SOUNDS =
|
||||
arrayOf(SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, STOP_VIDEO_RECORDING,
|
||||
TIMER_COUNTDOWN, TIMER_COUNTDOWN_2_SECONDS)
|
||||
</ID>
|
||||
<ID>MaxLineLength:MediaOutputHelper.kt$MediaOutputHelper$put(MediaStore.MediaColumns.DATA,
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString())
|
||||
</ID>
|
||||
<ID>MaxLineLength:PhotoProcessor.kt$PhotoProcessor$activity.config.savePhotosFolder =
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
|
||||
</ID>
|
||||
<ID>MaxLineLength:PhotoProcessor.kt$PhotoProcessor$document = document?.createFile("",
|
||||
path.substring(path.lastIndexOf('/') + 1)) ?: activity.getDocumentFile(path)
|
||||
</ID>
|
||||
<ID>MaxLineLength:PhotoProcessor.kt$PhotoProcessor$val activity: MainActivity</ID>
|
||||
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$OpenDeviceSettingsDialog(activity =
|
||||
this@SettingsActivity, message =
|
||||
getString(org.fossify.commons.R.string.allow_location_permission))
|
||||
</ID>
|
||||
<ID>
|
||||
MaxLineLength:SettingsActivity.kt$SettingsActivity$faqItems.add(FAQItem(org.fossify.commons.R.string.faq_2_title_commons,
|
||||
org.fossify.commons.R.string.faq_2_text_commons))
|
||||
</ID>
|
||||
<ID>
|
||||
MaxLineLength:SettingsActivity.kt$SettingsActivity$faqItems.add(FAQItem(org.fossify.commons.R.string.faq_6_title_commons,
|
||||
org.fossify.commons.R.string.faq_6_text_commons))
|
||||
</ID>
|
||||
<ID>
|
||||
MaxLineLength:SettingsActivity.kt$SettingsActivity$findItem(R.id.more_apps_from_us).isVisible
|
||||
= !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)
|
||||
</ID>
|
||||
<ID>
|
||||
MaxLineLength:SettingsActivity.kt$SettingsActivity$it.beGoneIf(settingsUseEnglishHolder.isGone()
|
||||
&& settingsPurchaseThankYouHolder.isGone() &&
|
||||
settingsLanguageHolder.isGone())
|
||||
</ID>
|
||||
<ID>
|
||||
MaxLineLength:SettingsActivity.kt$SettingsActivity$settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled
|
||||
|| Locale.getDefault().language != "en") && !isTiramisuPlus())
|
||||
</ID>
|
||||
<ID>
|
||||
MaxLineLength:SettingsActivity.kt$SettingsActivity$updateMaterialActivityViews(settingsCoordinator,
|
||||
settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
</ID>
|
||||
<ID>MaxLineLength:ShadowDrawable.kt$ShadowDrawable$if</ID>
|
||||
<ID>
|
||||
MaxLineLength:ShadowDrawable.kt$ShadowDrawable$obtainStyledAttributes.getColor(R.styleable.ShadowDrawable_android_shadowColor,
|
||||
ContextCompat.getColor(context, org.fossify.commons.R.color.md_grey_400_dark))
|
||||
</ID>
|
||||
<ID>MaxLineLength:ShadowDrawable.kt$ShadowDrawable$sharedBitmap =
|
||||
Bitmap.createBitmap(SHARED_BITMAP_BUFFER_SIZE, SHARED_BITMAP_BUFFER_SIZE,
|
||||
Bitmap.Config.ARGB_8888)
|
||||
</ID>
|
||||
<ID>MaxLineLength:ShadowDrawable.kt$ShadowDrawable$val shadowRadius =
|
||||
obtainStyledAttributes.getFloat(R.styleable.ShadowDrawable_android_shadowRadius,
|
||||
0.0f).coerceAtLeast(0.0f)
|
||||
</ID>
|
||||
<ID>MaxLineLength:VideoQualityManager.kt$VideoQualityManager$val selectionIndex =
|
||||
mediaSizeStore.getCurrentSizeIndex(isPhotoCapture = false, isFrontCamera =
|
||||
isFrontCamera).coerceAtLeast(0)
|
||||
</ID>
|
||||
<ID>NestedBlockDepth:ImageQualityManager.kt$ImageQualityManager$fun
|
||||
initSupportedQualities()
|
||||
</ID>
|
||||
<ID>NestedBlockDepth:ImageSaver.kt$ImageSaver$private fun
|
||||
copyTempFileToDestination(tempFile: File)
|
||||
</ID>
|
||||
<ID>NestedBlockDepth:MediaOutputHelper.kt$MediaOutputHelper$fun getImageMediaOutput():
|
||||
MediaOutput.ImageCaptureOutput
|
||||
</ID>
|
||||
<ID>NestedBlockDepth:MediaOutputHelper.kt$MediaOutputHelper$fun getVideoMediaOutput():
|
||||
MediaOutput.VideoCaptureOutput
|
||||
</ID>
|
||||
<ID>NestedBlockDepth:MediaOutputHelper.kt$MediaOutputHelper$private fun
|
||||
getUriForFilePath(path: String): Uri?
|
||||
</ID>
|
||||
<ID>NestedBlockDepth:PhotoProcessor.kt$PhotoProcessor$override fun doInBackground(vararg
|
||||
params: ByteArray): String
|
||||
</ID>
|
||||
<ID>NestedBlockDepth:VideoQualityManager.kt$VideoQualityManager$fun
|
||||
initSupportedQualities(cameraProvider: ProcessCameraProvider)
|
||||
</ID>
|
||||
<ID>ReturnCount:ImageSaver.kt$ImageSaver$@SuppressLint("RestrictedApi") private fun
|
||||
saveImageToTempFile(): File?
|
||||
</ID>
|
||||
<ID>ReturnCount:MediaActionSound.kt$MediaActionSound$private fun loadSound(sound:
|
||||
SoundState): Int
|
||||
</ID>
|
||||
<ID>ReturnCount:MediaOutputHelper.kt$MediaOutputHelper$private fun
|
||||
getFileDescriptorMediaOutput(): MediaOutput.FileDescriptorMediaOutput?
|
||||
</ID>
|
||||
<ID>ReturnCount:MediaOutputHelper.kt$MediaOutputHelper$private fun getUriForFilePath(path:
|
||||
String): Uri?
|
||||
</ID>
|
||||
<ID>ReturnCount:PhotoProcessor.kt$PhotoProcessor$override fun doInBackground(vararg params:
|
||||
ByteArray): String
|
||||
</ID>
|
||||
<ID>ReturnCount:PhotoProcessor.kt$PhotoProcessor$private fun rotate(bitmap: Bitmap, degree:
|
||||
Int): Bitmap?
|
||||
</ID>
|
||||
<ID>SwallowedException:BitmapUtils.kt$BitmapUtils$ex: OutOfMemoryError</ID>
|
||||
<ID>SwallowedException:CameraXPreview.kt$CameraXPreview$e: Exception</ID>
|
||||
<ID>SwallowedException:ImageUtil.kt$ImageUtil$e: IOException</ID>
|
||||
<ID>SwallowedException:MediaOutputHelper.kt$MediaOutputHelper$e: Exception</ID>
|
||||
<ID>SwallowedException:PhotoProcessor.kt$PhotoProcessor$e: Exception</ID>
|
||||
<ID>SwallowedException:PhotoProcessor.kt$PhotoProcessor$e: OutOfMemoryError</ID>
|
||||
<ID>ThrowsCount:ImageUtil.kt$ImageUtil$@Throws(CodecFailedException::class) private fun
|
||||
cropJpegByteArray( data: ByteArray, cropRect: Rect, @IntRange(from = 1, to = 100)
|
||||
jpegQuality: Int, ): ByteArray
|
||||
</ID>
|
||||
<ID>TooGenericExceptionCaught:CameraXPreview.kt$CameraXPreview$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:ImageQualityManager.kt$ImageQualityManager$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:MediaOutputHelper.kt$MediaOutputHelper$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:PhotoProcessor.kt$PhotoProcessor$e: Exception</ID>
|
||||
<ID>TooGenericExceptionCaught:VideoQualityManager.kt$VideoQualityManager$e: Exception</ID>
|
||||
<ID>TooManyFunctions:CameraXPreview.kt$CameraXPreview : MyPreviewDefaultLifecycleObserver
|
||||
</ID>
|
||||
<ID>TooManyFunctions:CameraXPreviewListener.kt$CameraXPreviewListener</ID>
|
||||
<ID>TooManyFunctions:MainActivity.kt$MainActivity :
|
||||
SimpleActivityMediaSavedListenerCameraXPreviewListener
|
||||
</ID>
|
||||
<ID>TooManyFunctions:MediaOutputHelper.kt$MediaOutputHelper</ID>
|
||||
<ID>TooManyFunctions:MySize.kt$MySize</ID>
|
||||
<ID>TooManyFunctions:SettingsActivity.kt$SettingsActivity : SimpleActivity</ID>
|
||||
<ID>TooManyFunctions:ShadowDrawable.kt$ShadowDrawable : Drawable</ID>
|
||||
<ID>TooManyFunctions:VideoQuality.kt$VideoQuality</ID>
|
||||
<ID>UnusedPrivateProperty:ImageUtil.kt$ImageUtil$col</ID>
|
||||
<ID>UnusedPrivateProperty:ImageUtil.kt$ImageUtil$row</ID>
|
||||
<ID>UseCheckOrError:CameraXPreview.kt$CameraXPreview$throw IllegalStateException("Camera
|
||||
initialization failed.")
|
||||
</ID>
|
||||
<ID>UseCheckOrError:MainActivity.kt$MainActivity.<no name provided>$throw
|
||||
IllegalStateException("Unsupported tab position ${tab.position}")
|
||||
</ID>
|
||||
<ID>VariableNaming:FocusCircleView.kt$FocusCircleView$private val CIRCLE_DURATION = 500L
|
||||
</ID>
|
||||
<ID>VariableNaming:FocusCircleView.kt$FocusCircleView$private val CIRCLE_RADIUS = 50f</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import android.view.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import androidx.camera.core.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import androidx.camera.core.ImageCapture.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import androidx.camera.video.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import org.fossify.camera.extensions.*</ID>
|
||||
<ID>WildcardImport:CameraXPreview.kt$import org.fossify.camera.helpers.*</ID>
|
||||
<ID>WildcardImport:ImageSaver.kt$import java.io.*</ID>
|
||||
<ID>WildcardImport:ImageUtil.kt$import android.graphics.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import android.view.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import androidx.core.view.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import androidx.transition.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import org.fossify.camera.helpers.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import org.fossify.commons.extensions.*</ID>
|
||||
<ID>WildcardImport:MainActivity.kt$import org.fossify.commons.helpers.*</ID>
|
||||
<ID>WildcardImport:MediaOutputHelper.kt$import org.fossify.commons.extensions.*</ID>
|
||||
<ID>WildcardImport:PhotoProcessor.kt$import org.fossify.commons.extensions.*</ID>
|
||||
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.commons.dialogs.*</ID>
|
||||
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.commons.extensions.*</ID>
|
||||
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.commons.helpers.*</ID>
|
||||
<ID>WildcardImport:ShadowDrawable.kt$import android.graphics.*</ID>
|
||||
</CurrentIssues>
|
||||
</SmellBaseline>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
tools:node="remove" />
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:name="org.fossify.commons.FossifyApp"
|
||||
android:allowBackup="true"
|
||||
android:appCategory="image"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
@@ -89,14 +89,14 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.simplemobiletools.commons.activities.AboutActivity"
|
||||
android:name="org.fossify.commons.activities.AboutActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:exported="false"
|
||||
android:label="@string/about"
|
||||
android:parentActivityName=".activities.SettingsActivity" />
|
||||
|
||||
<activity
|
||||
android:name="com.simplemobiletools.commons.activities.CustomizationActivity"
|
||||
android:name="org.fossify.commons.activities.CustomizationActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:exported="false"
|
||||
android:label="@string/customize_colors"
|
||||
|
||||
BIN
app/src/main/ic_launcher-playstore.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
@@ -1,11 +0,0 @@
|
||||
package com.simplemobiletools.camera
|
||||
|
||||
import android.app.Application
|
||||
import com.simplemobiletools.commons.extensions.checkUseEnglish
|
||||
|
||||
class App : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
checkUseEnglish()
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.simplemobiletools.camera.activities
|
||||
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
|
||||
open class SimpleActivity : BaseSimpleActivity() {
|
||||
override fun getAppIconIDs() = arrayListOf(
|
||||
R.mipmap.ic_launcher_red,
|
||||
R.mipmap.ic_launcher_pink,
|
||||
R.mipmap.ic_launcher_purple,
|
||||
R.mipmap.ic_launcher_deep_purple,
|
||||
R.mipmap.ic_launcher_indigo,
|
||||
R.mipmap.ic_launcher_blue,
|
||||
R.mipmap.ic_launcher_light_blue,
|
||||
R.mipmap.ic_launcher_cyan,
|
||||
R.mipmap.ic_launcher_teal,
|
||||
R.mipmap.ic_launcher_green,
|
||||
R.mipmap.ic_launcher_light_green,
|
||||
R.mipmap.ic_launcher_lime,
|
||||
R.mipmap.ic_launcher_yellow,
|
||||
R.mipmap.ic_launcher_amber,
|
||||
R.mipmap.ic_launcher,
|
||||
R.mipmap.ic_launcher_deep_orange,
|
||||
R.mipmap.ic_launcher_brown,
|
||||
R.mipmap.ic_launcher_blue_grey,
|
||||
R.mipmap.ic_launcher_grey_black
|
||||
)
|
||||
|
||||
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.simplemobiletools.camera.extensions
|
||||
|
||||
import android.view.View
|
||||
import com.simplemobiletools.commons.helpers.SHORT_ANIMATION_DURATION
|
||||
|
||||
fun View.fadeIn() {
|
||||
animate().alpha(1f).setDuration(SHORT_ANIMATION_DURATION).withStartAction { isClickable = true }.start()
|
||||
}
|
||||
|
||||
fun View.fadeOut() {
|
||||
animate().alpha(0f).setDuration(SHORT_ANIMATION_DURATION).withEndAction { isClickable = false }.start()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.activities
|
||||
package org.fossify.camera.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
@@ -23,24 +23,23 @@ import com.bumptech.glide.request.RequestOptions
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.simplemobiletools.camera.BuildConfig
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.databinding.ActivityMainBinding
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.extensions.fadeIn
|
||||
import com.simplemobiletools.camera.extensions.fadeOut
|
||||
import com.simplemobiletools.camera.extensions.setShadowIcon
|
||||
import com.simplemobiletools.camera.extensions.toFlashModeId
|
||||
import com.simplemobiletools.camera.helpers.*
|
||||
import com.simplemobiletools.camera.implementations.CameraXInitializer
|
||||
import com.simplemobiletools.camera.implementations.CameraXPreviewListener
|
||||
import com.simplemobiletools.camera.interfaces.MyPreview
|
||||
import com.simplemobiletools.camera.models.ResolutionOption
|
||||
import com.simplemobiletools.camera.models.TimerMode
|
||||
import com.simplemobiletools.camera.views.FocusCircleView
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.Release
|
||||
import org.fossify.camera.BuildConfig
|
||||
import org.fossify.camera.R
|
||||
import org.fossify.camera.databinding.ActivityMainBinding
|
||||
import org.fossify.camera.extensions.config
|
||||
import org.fossify.camera.extensions.fadeIn
|
||||
import org.fossify.camera.extensions.fadeOut
|
||||
import org.fossify.camera.extensions.setShadowIcon
|
||||
import org.fossify.camera.extensions.toFlashModeId
|
||||
import org.fossify.camera.helpers.*
|
||||
import org.fossify.camera.implementations.CameraXInitializer
|
||||
import org.fossify.camera.implementations.CameraXPreviewListener
|
||||
import org.fossify.camera.interfaces.MyPreview
|
||||
import org.fossify.camera.models.ResolutionOption
|
||||
import org.fossify.camera.models.TimerMode
|
||||
import org.fossify.camera.views.FocusCircleView
|
||||
import org.fossify.commons.extensions.*
|
||||
import org.fossify.commons.helpers.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.abs
|
||||
|
||||
@@ -78,7 +77,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
else -> throw IllegalStateException("Unsupported tab position ${tab.position}")
|
||||
}
|
||||
} else {
|
||||
toast(com.simplemobiletools.commons.R.string.no_audio_permissions)
|
||||
toast(org.fossify.commons.R.string.no_audio_permissions)
|
||||
selectPhotoTab()
|
||||
if (isVideoCaptureIntent()) {
|
||||
finish()
|
||||
@@ -96,11 +95,11 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
initVariables()
|
||||
tryInitCamera()
|
||||
supportActionBar?.hide()
|
||||
checkWhatsNewDialog()
|
||||
setupOrientationEventListener()
|
||||
|
||||
val windowInsetsController = ViewCompat.getWindowInsetsController(window.decorView)
|
||||
windowInsetsController?.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
windowInsetsController?.systemBarsBehavior =
|
||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
windowInsetsController?.hide(WindowInsetsCompat.Type.statusBars())
|
||||
|
||||
if (isOreoMr1Plus()) {
|
||||
@@ -109,9 +108,9 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
} else {
|
||||
window.addFlags(
|
||||
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
|
||||
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
||||
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
||||
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -130,7 +129,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
ensureTransparentNavigationBar()
|
||||
|
||||
if (ViewCompat.getWindowInsetsController(window.decorView) == null) {
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
window.decorView.systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
if (grantedRecordAudioPermission) {
|
||||
initializeCamera(false)
|
||||
} else {
|
||||
toast(com.simplemobiletools.commons.R.string.no_audio_permissions)
|
||||
toast(org.fossify.commons.R.string.no_audio_permissions)
|
||||
if (isThirdPartyIntent()) {
|
||||
finish()
|
||||
} else {
|
||||
@@ -247,7 +247,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toast(com.simplemobiletools.commons.R.string.no_camera_permissions)
|
||||
toast(org.fossify.commons.R.string.no_camera_permissions)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
@@ -265,7 +265,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
|
||||
private fun handleStoragePermission(callback: (granted: Boolean) -> Unit) {
|
||||
if (isTiramisuPlus()) {
|
||||
val mediaPermissionIds = mutableListOf(PERMISSION_READ_MEDIA_IMAGES, PERMISSION_READ_MEDIA_VIDEO)
|
||||
val mediaPermissionIds =
|
||||
mutableListOf(PERMISSION_READ_MEDIA_IMAGES, PERMISSION_READ_MEDIA_VIDEO)
|
||||
if (isUpsideDownCakePlus()) {
|
||||
mediaPermissionIds.add(PERMISSION_READ_MEDIA_VISUAL_USER_SELECTED)
|
||||
}
|
||||
@@ -278,14 +279,18 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
|
||||
private fun isThirdPartyIntent() = isVideoCaptureIntent() || isImageCaptureIntent()
|
||||
|
||||
private fun isImageCaptureIntent(): Boolean = intent?.action == MediaStore.ACTION_IMAGE_CAPTURE || intent?.action == MediaStore.ACTION_IMAGE_CAPTURE_SECURE
|
||||
private fun isImageCaptureIntent(): Boolean =
|
||||
intent?.action == MediaStore.ACTION_IMAGE_CAPTURE || intent?.action == MediaStore.ACTION_IMAGE_CAPTURE_SECURE
|
||||
|
||||
private fun isVideoCaptureIntent(): Boolean = intent?.action == MediaStore.ACTION_VIDEO_CAPTURE
|
||||
|
||||
private fun createToggleGroup(): MaterialButtonToggleGroup {
|
||||
return MaterialButtonToggleGroup(this).apply {
|
||||
isSingleSelection = true
|
||||
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +313,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
topMargin = safeInsetTop
|
||||
}
|
||||
|
||||
val marginBottom = safeInsetBottom + navigationBarHeight + resources.getDimensionPixelSize(com.simplemobiletools.commons.R.dimen.bigger_margin)
|
||||
val marginBottom =
|
||||
safeInsetBottom + navigationBarHeight + resources.getDimensionPixelSize(org.fossify.commons.R.dimen.bigger_margin)
|
||||
|
||||
binding.shutter.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
bottomMargin = marginBottom
|
||||
@@ -436,7 +442,12 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onFling(event1: MotionEvent?, event2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean {
|
||||
override fun onFling(
|
||||
event1: MotionEvent?,
|
||||
event2: MotionEvent?,
|
||||
velocityX: Float,
|
||||
velocityY: Float
|
||||
): Boolean {
|
||||
if (event1 == null || event2 == null) {
|
||||
return true
|
||||
}
|
||||
@@ -481,7 +492,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
|
||||
private fun showLastMediaPreview() {
|
||||
if (mPreviewUri != null) {
|
||||
val path = applicationContext.getRealPathFromURI(mPreviewUri!!) ?: mPreviewUri!!.toString()
|
||||
val path =
|
||||
applicationContext.getRealPathFromURI(mPreviewUri!!) ?: mPreviewUri!!.toString()
|
||||
openPathIntent(path, false, BuildConfig.APPLICATION_ID)
|
||||
}
|
||||
}
|
||||
@@ -534,7 +546,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
}
|
||||
|
||||
private fun setupPreviewImage(isPhoto: Boolean) {
|
||||
val uri = if (isPhoto) MediaStore.Images.Media.EXTERNAL_CONTENT_URI else MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
val uri =
|
||||
if (isPhoto) MediaStore.Images.Media.EXTERNAL_CONTENT_URI else MediaStore.Video.Media.EXTERNAL_CONTENT_URI
|
||||
val lastMediaId = getLatestMediaId(uri)
|
||||
if (lastMediaId == 0L) {
|
||||
return
|
||||
@@ -568,9 +581,12 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
|
||||
private fun hasPhotoModePermissions(): Boolean {
|
||||
return if (isTiramisuPlus()) {
|
||||
var hasMediaPermission = hasPermission(PERMISSION_READ_MEDIA_IMAGES) || hasPermission(PERMISSION_READ_MEDIA_VIDEO)
|
||||
var hasMediaPermission = hasPermission(PERMISSION_READ_MEDIA_IMAGES) || hasPermission(
|
||||
PERMISSION_READ_MEDIA_VIDEO
|
||||
)
|
||||
if (isUpsideDownCakePlus()) {
|
||||
hasMediaPermission = hasMediaPermission || hasPermission(PERMISSION_READ_MEDIA_VISUAL_USER_SELECTED)
|
||||
hasMediaPermission =
|
||||
hasMediaPermission || hasPermission(PERMISSION_READ_MEDIA_VISUAL_USER_SELECTED)
|
||||
}
|
||||
hasMediaPermission && hasPermission(PERMISSION_CAMERA)
|
||||
} else {
|
||||
@@ -582,16 +598,23 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
return if (isTiramisuPlus()) {
|
||||
var hasMediaPermission = hasPermission(PERMISSION_READ_MEDIA_VIDEO)
|
||||
if (isUpsideDownCakePlus()) {
|
||||
hasMediaPermission = hasMediaPermission || hasPermission(PERMISSION_READ_MEDIA_VISUAL_USER_SELECTED)
|
||||
hasMediaPermission =
|
||||
hasMediaPermission || hasPermission(PERMISSION_READ_MEDIA_VISUAL_USER_SELECTED)
|
||||
}
|
||||
hasMediaPermission && hasPermission(PERMISSION_CAMERA) && hasPermission(PERMISSION_RECORD_AUDIO)
|
||||
hasMediaPermission && hasPermission(PERMISSION_CAMERA) && hasPermission(
|
||||
PERMISSION_RECORD_AUDIO
|
||||
)
|
||||
} else {
|
||||
hasPermission(PERMISSION_WRITE_STORAGE) && hasPermission(PERMISSION_CAMERA) && hasPermission(PERMISSION_RECORD_AUDIO)
|
||||
hasPermission(PERMISSION_WRITE_STORAGE) && hasPermission(PERMISSION_CAMERA) && hasPermission(
|
||||
PERMISSION_RECORD_AUDIO
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupOrientationEventListener() {
|
||||
mOrientationEventListener = object : OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) {
|
||||
mOrientationEventListener = object : OrientationEventListener(
|
||||
this, SensorManager.SENSOR_DELAY_NORMAL
|
||||
) {
|
||||
override fun onOrientationChanged(orientation: Int) {
|
||||
if (isDestroyed) {
|
||||
mOrientationEventListener.disable()
|
||||
@@ -632,10 +655,11 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
}
|
||||
}
|
||||
|
||||
private fun rotate(view: View, degrees: Int) = view.animate().rotation(degrees.toFloat()).start()
|
||||
private fun rotate(view: View, degrees: Int) =
|
||||
view.animate().rotation(degrees.toFloat()).start()
|
||||
|
||||
override fun setHasFrontAndBackCamera(hasFrontAndBack: Boolean) {
|
||||
binding.toggleCamera?.beVisibleIf(hasFrontAndBack)
|
||||
binding.toggleCamera.beVisibleIf(hasFrontAndBack)
|
||||
}
|
||||
|
||||
override fun setFlashAvailable(available: Boolean) {
|
||||
@@ -823,7 +847,10 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
mediaSizeToggleGroup.children.map { it as MaterialButton }.forEach(::setButtonColors)
|
||||
}
|
||||
|
||||
private fun createButton(resolutionOption: ResolutionOption, onClick: (clickedViewId: Int) -> Unit): MaterialButton {
|
||||
private fun createButton(
|
||||
resolutionOption: ResolutionOption,
|
||||
onClick: (clickedViewId: Int) -> Unit
|
||||
): MaterialButton {
|
||||
val params = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
weight = 1f
|
||||
}
|
||||
@@ -862,8 +889,14 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
|
||||
private fun setButtonColors(button: MaterialButton) {
|
||||
val primaryColor = getProperPrimaryColor()
|
||||
val states = arrayOf(intArrayOf(-android.R.attr.state_checked), intArrayOf(android.R.attr.state_checked))
|
||||
val iconColors = intArrayOf(ContextCompat.getColor(this, com.simplemobiletools.commons.R.color.md_grey_white), primaryColor)
|
||||
val states = arrayOf(
|
||||
intArrayOf(-android.R.attr.state_checked),
|
||||
intArrayOf(android.R.attr.state_checked)
|
||||
)
|
||||
val iconColors = intArrayOf(
|
||||
ContextCompat.getColor(this, org.fossify.commons.R.color.md_grey_white),
|
||||
primaryColor
|
||||
)
|
||||
button.iconTint = ColorStateList(states, iconColors)
|
||||
}
|
||||
|
||||
@@ -872,11 +905,31 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
val constraintSet = ConstraintSet()
|
||||
constraintSet.clone(viewHolder)
|
||||
if (requiresCentering) {
|
||||
constraintSet.connect(previewView.id, ConstraintSet.TOP, topOptions.id, ConstraintSet.BOTTOM)
|
||||
constraintSet.connect(previewView.id, ConstraintSet.BOTTOM, cameraModeHolder.id, ConstraintSet.TOP)
|
||||
constraintSet.connect(
|
||||
previewView.id,
|
||||
ConstraintSet.TOP,
|
||||
topOptions.id,
|
||||
ConstraintSet.BOTTOM
|
||||
)
|
||||
constraintSet.connect(
|
||||
previewView.id,
|
||||
ConstraintSet.BOTTOM,
|
||||
cameraModeHolder.id,
|
||||
ConstraintSet.TOP
|
||||
)
|
||||
} else {
|
||||
constraintSet.connect(previewView.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
|
||||
constraintSet.connect(previewView.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
|
||||
constraintSet.connect(
|
||||
previewView.id,
|
||||
ConstraintSet.TOP,
|
||||
ConstraintSet.PARENT_ID,
|
||||
ConstraintSet.TOP
|
||||
)
|
||||
constraintSet.connect(
|
||||
previewView.id,
|
||||
ConstraintSet.BOTTOM,
|
||||
ConstraintSet.PARENT_ID,
|
||||
ConstraintSet.BOTTOM
|
||||
)
|
||||
}
|
||||
constraintSet.applyTo(viewHolder)
|
||||
}
|
||||
@@ -887,7 +940,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
setupPreviewImage(true)
|
||||
Intent(BROADCAST_REFRESH_MEDIA).apply {
|
||||
putExtra(REFRESH_PATH, path)
|
||||
`package` = "com.simplemobiletools.gallery"
|
||||
`package` = "org.fossify.gallery"
|
||||
sendBroadcast(this)
|
||||
}
|
||||
}
|
||||
@@ -933,23 +986,11 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||
|
||||
private fun resetViewsOnTimerFinish() = binding.apply {
|
||||
arrayOf(topOptions, toggleCamera, lastPhotoVideoPreview, cameraModeHolder).forEach {
|
||||
it?.fadeIn()
|
||||
it?.beVisible()
|
||||
it.fadeIn()
|
||||
it.beVisible()
|
||||
}
|
||||
|
||||
timerText.beGone()
|
||||
shutter.setImageState(intArrayOf(-R.attr.state_timer_cancel), true)
|
||||
}
|
||||
|
||||
private fun checkWhatsNewDialog() {
|
||||
arrayListOf<Release>().apply {
|
||||
add(Release(33, R.string.release_33))
|
||||
add(Release(35, R.string.release_35))
|
||||
add(Release(39, R.string.release_39))
|
||||
add(Release(44, R.string.release_44))
|
||||
add(Release(46, R.string.release_46))
|
||||
add(Release(52, R.string.release_52))
|
||||
checkWhatsNew(this, BuildConfig.VERSION_CODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
package com.simplemobiletools.camera.activities
|
||||
package org.fossify.camera.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import com.simplemobiletools.camera.BuildConfig
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.databinding.ActivitySettingsBinding
|
||||
import com.simplemobiletools.camera.extensions.checkLocationPermission
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.models.CaptureMode
|
||||
import com.simplemobiletools.commons.dialogs.*
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.FAQItem
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import org.fossify.camera.BuildConfig
|
||||
import org.fossify.camera.R
|
||||
import org.fossify.camera.databinding.ActivitySettingsBinding
|
||||
import org.fossify.camera.extensions.checkLocationPermission
|
||||
import org.fossify.camera.extensions.config
|
||||
import org.fossify.camera.models.CaptureMode
|
||||
import org.fossify.commons.dialogs.*
|
||||
import org.fossify.commons.extensions.*
|
||||
import org.fossify.commons.helpers.*
|
||||
import org.fossify.commons.models.FAQItem
|
||||
import org.fossify.commons.models.RadioItem
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@@ -27,7 +27,12 @@ class SettingsActivity : SimpleActivity() {
|
||||
setupOptionsMenu()
|
||||
refreshMenuItems()
|
||||
|
||||
updateMaterialActivityViews(settingsCoordinator, settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
updateMaterialActivityViews(
|
||||
settingsCoordinator,
|
||||
settingsHolder,
|
||||
useTransparentNavigation = true,
|
||||
useTopSearchMenu = false
|
||||
)
|
||||
setupMaterialScrollListener(settingsNestedScrollview, settingsToolbar)
|
||||
}
|
||||
}
|
||||
@@ -65,7 +70,8 @@ class SettingsActivity : SimpleActivity() {
|
||||
|
||||
private fun refreshMenuItems() {
|
||||
binding.settingsToolbar.menu.apply {
|
||||
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)
|
||||
findItem(R.id.more_apps_from_us).isVisible =
|
||||
!resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,12 +130,29 @@ class SettingsActivity : SimpleActivity() {
|
||||
FAQItem(R.string.faq_1_title, R.string.faq_1_text)
|
||||
)
|
||||
|
||||
if (!resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)) {
|
||||
faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_2_title_commons, com.simplemobiletools.commons.R.string.faq_2_text_commons))
|
||||
faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_6_title_commons, com.simplemobiletools.commons.R.string.faq_6_text_commons))
|
||||
if (!resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)) {
|
||||
faqItems.add(
|
||||
FAQItem(
|
||||
org.fossify.commons.R.string.faq_2_title_commons,
|
||||
org.fossify.commons.R.string.faq_2_text_commons
|
||||
)
|
||||
)
|
||||
faqItems.add(
|
||||
FAQItem(
|
||||
org.fossify.commons.R.string.faq_6_title_commons,
|
||||
org.fossify.commons.R.string.faq_6_text_commons
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)
|
||||
startAboutActivity(
|
||||
appNameId = R.string.app_name,
|
||||
licenseMask = licenses,
|
||||
versionName = BuildConfig.VERSION_NAME,
|
||||
repositoryName = "Camera",
|
||||
faqItems = faqItems,
|
||||
showFAQBeforeMail = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun getLastPart(path: String): String {
|
||||
@@ -182,7 +205,10 @@ class SettingsActivity : SimpleActivity() {
|
||||
if (checkLocationPermission()) {
|
||||
updateSavePhotoVideoLocationConfig(true)
|
||||
} else {
|
||||
OpenDeviceSettingsDialog(activity = this@SettingsActivity, message = getString(com.simplemobiletools.commons.R.string.allow_location_permission))
|
||||
OpenDeviceSettingsDialog(
|
||||
activity = this@SettingsActivity,
|
||||
message = getString(org.fossify.commons.R.string.allow_location_permission)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,7 +228,12 @@ class SettingsActivity : SimpleActivity() {
|
||||
settingsSavePhotos.text = getLastPart(config.savePhotosFolder)
|
||||
settingsSavePhotosHolder.setOnClickListener {
|
||||
if (isOrWasThankYouInstalled()) {
|
||||
FilePickerDialog(this@SettingsActivity, config.savePhotosFolder, false, showFAB = true) {
|
||||
FilePickerDialog(
|
||||
this@SettingsActivity,
|
||||
config.savePhotosFolder,
|
||||
false,
|
||||
showFAB = true
|
||||
) {
|
||||
val path = it
|
||||
handleSAFDialog(it) { success ->
|
||||
if (success) {
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.fossify.camera.activities
|
||||
|
||||
import org.fossify.camera.R
|
||||
import org.fossify.commons.activities.BaseSimpleActivity
|
||||
|
||||
open class SimpleActivity : BaseSimpleActivity() {
|
||||
override fun getAppIconIDs() = arrayListOf(
|
||||
R.mipmap.ic_launcher_red,
|
||||
R.mipmap.ic_launcher_pink,
|
||||
R.mipmap.ic_launcher_purple,
|
||||
R.mipmap.ic_launcher_deep_purple,
|
||||
R.mipmap.ic_launcher_indigo,
|
||||
R.mipmap.ic_launcher_blue,
|
||||
R.mipmap.ic_launcher_light_blue,
|
||||
R.mipmap.ic_launcher_cyan,
|
||||
R.mipmap.ic_launcher_teal,
|
||||
R.mipmap.ic_launcher_green,
|
||||
R.mipmap.ic_launcher_light_green,
|
||||
R.mipmap.ic_launcher_lime,
|
||||
R.mipmap.ic_launcher_yellow,
|
||||
R.mipmap.ic_launcher_amber,
|
||||
R.mipmap.ic_launcher,
|
||||
R.mipmap.ic_launcher_deep_orange,
|
||||
R.mipmap.ic_launcher_brown,
|
||||
R.mipmap.ic_launcher_blue_grey,
|
||||
R.mipmap.ic_launcher_grey_black
|
||||
)
|
||||
|
||||
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.simplemobiletools.camera.activities
|
||||
package org.fossify.camera.activities
|
||||
|
||||
import android.content.Intent
|
||||
import com.simplemobiletools.commons.activities.BaseSplashActivity
|
||||
import org.fossify.commons.activities.BaseSplashActivity
|
||||
|
||||
class SplashActivity : BaseSplashActivity() {
|
||||
override fun initActivity() {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.extensions
|
||||
package org.fossify.camera.extensions
|
||||
|
||||
import androidx.camera.core.CameraSelector
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.simplemobiletools.camera.extensions
|
||||
package org.fossify.camera.extensions
|
||||
|
||||
import android.content.Context
|
||||
import com.simplemobiletools.camera.helpers.Config
|
||||
import com.simplemobiletools.commons.extensions.hasPermission
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_ACCESS_COARSE_LOCATION
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_ACCESS_FINE_LOCATION
|
||||
import org.fossify.camera.helpers.Config
|
||||
import org.fossify.commons.extensions.hasPermission
|
||||
import org.fossify.commons.helpers.PERMISSION_ACCESS_COARSE_LOCATION
|
||||
import org.fossify.commons.helpers.PERMISSION_ACCESS_FINE_LOCATION
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
@@ -28,6 +28,7 @@ fun Context.getOutputMediaFilePath(isPhoto: Boolean): String {
|
||||
"${mediaStorageDir.path}/$mediaName.mp4"
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getOutputMediaFileName(isPhoto: Boolean): String {
|
||||
val mediaName = getRandomMediaName(isPhoto)
|
||||
return if (isPhoto) {
|
||||
@@ -47,5 +48,7 @@ fun getRandomMediaName(isPhoto: Boolean): String {
|
||||
}
|
||||
|
||||
fun Context.checkLocationPermission(): Boolean {
|
||||
return hasPermission(PERMISSION_ACCESS_FINE_LOCATION) || hasPermission(PERMISSION_ACCESS_COARSE_LOCATION)
|
||||
return hasPermission(PERMISSION_ACCESS_FINE_LOCATION) || hasPermission(
|
||||
PERMISSION_ACCESS_COARSE_LOCATION
|
||||
)
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.simplemobiletools.camera.extensions
|
||||
package org.fossify.camera.extensions
|
||||
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.ImageCapture
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.helpers.FLASH_ALWAYS_ON
|
||||
import com.simplemobiletools.camera.helpers.FLASH_AUTO
|
||||
import com.simplemobiletools.camera.helpers.FLASH_OFF
|
||||
import com.simplemobiletools.camera.helpers.FLASH_ON
|
||||
import org.fossify.camera.R
|
||||
import org.fossify.camera.helpers.FLASH_ALWAYS_ON
|
||||
import org.fossify.camera.helpers.FLASH_AUTO
|
||||
import org.fossify.camera.helpers.FLASH_OFF
|
||||
import org.fossify.camera.helpers.FLASH_ON
|
||||
|
||||
fun Int.toCameraXFlashMode(): Int {
|
||||
return when (this) {
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.simplemobiletools.camera.extensions
|
||||
package org.fossify.camera.extensions
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.views.ShadowDrawable
|
||||
import org.fossify.camera.R
|
||||
import org.fossify.camera.views.ShadowDrawable
|
||||
|
||||
fun MaterialButton.setShadowIcon(@DrawableRes drawableResId: Int) {
|
||||
icon = ShadowDrawable(context, drawableResId, R.style.TopIconShadow)
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.simplemobiletools.camera.extensions
|
||||
package org.fossify.camera.extensions
|
||||
|
||||
import androidx.camera.video.Quality
|
||||
import com.simplemobiletools.camera.models.VideoQuality
|
||||
import org.fossify.camera.models.VideoQuality
|
||||
|
||||
fun Quality.toVideoQuality(): VideoQuality {
|
||||
return when (this) {
|
||||
14
app/src/main/kotlin/org/fossify/camera/extensions/View.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
package org.fossify.camera.extensions
|
||||
|
||||
import android.view.View
|
||||
import org.fossify.commons.helpers.SHORT_ANIMATION_DURATION
|
||||
|
||||
fun View.fadeIn() {
|
||||
animate().alpha(1f).setDuration(SHORT_ANIMATION_DURATION).withStartAction { isClickable = true }
|
||||
.start()
|
||||
}
|
||||
|
||||
fun View.fadeOut() {
|
||||
animate().alpha(0f).setDuration(SHORT_ANIMATION_DURATION).withEndAction { isClickable = false }
|
||||
.start()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
@@ -10,7 +10,10 @@ import kotlin.math.sqrt
|
||||
object BitmapUtils {
|
||||
private const val INLINE_BITMAP_MAX_PIXEL_NUM = 50 * 1024
|
||||
|
||||
fun makeBitmap(jpegData: ByteArray, maxNumOfPixels: Int = INLINE_BITMAP_MAX_PIXEL_NUM): Bitmap? {
|
||||
fun makeBitmap(
|
||||
jpegData: ByteArray,
|
||||
maxNumOfPixels: Int = INLINE_BITMAP_MAX_PIXEL_NUM
|
||||
): Bitmap? {
|
||||
return try {
|
||||
val options = BitmapFactory.Options()
|
||||
options.inJustDecodeBounds = true
|
||||
@@ -33,7 +36,11 @@ object BitmapUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeSampleSize(options: BitmapFactory.Options, minSideLength: Int, maxNumOfPixels: Int): Int {
|
||||
private fun computeSampleSize(
|
||||
options: BitmapFactory.Options,
|
||||
minSideLength: Int,
|
||||
maxNumOfPixels: Int
|
||||
): Int {
|
||||
val initialSize = computeInitialSampleSize(
|
||||
options, minSideLength,
|
||||
maxNumOfPixels
|
||||
@@ -50,11 +57,17 @@ object BitmapUtils {
|
||||
return roundedSize
|
||||
}
|
||||
|
||||
private fun computeInitialSampleSize(options: BitmapFactory.Options, minSideLength: Int, maxNumOfPixels: Int): Int {
|
||||
private fun computeInitialSampleSize(
|
||||
options: BitmapFactory.Options,
|
||||
minSideLength: Int,
|
||||
maxNumOfPixels: Int
|
||||
): Int {
|
||||
val w = options.outWidth.toDouble()
|
||||
val h = options.outHeight.toDouble()
|
||||
val lowerBound = if (maxNumOfPixels < 0) 1 else ceil(sqrt(w * h / maxNumOfPixels)).toInt()
|
||||
val upperBound = if (minSideLength < 0) 128 else floor(w / minSideLength).coerceAtMost(floor(h / minSideLength)).toInt()
|
||||
val upperBound =
|
||||
if (minSideLength < 0) 128 else floor(w / minSideLength).coerceAtMost(floor(h / minSideLength))
|
||||
.toInt()
|
||||
if (upperBound < lowerBound) {
|
||||
// return the larger one when there is no overlapping zone.
|
||||
return lowerBound
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
import androidx.camera.core.CameraState
|
||||
import androidx.camera.core.ImageCapture
|
||||
import androidx.camera.video.VideoRecordEvent
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import org.fossify.camera.R
|
||||
import org.fossify.commons.extensions.toast
|
||||
|
||||
class CameraErrorHandler(
|
||||
private val context: Context,
|
||||
@@ -15,11 +15,19 @@ class CameraErrorHandler(
|
||||
fun handleCameraError(error: CameraState.StateError?) {
|
||||
when (error?.code) {
|
||||
CameraState.ERROR_MAX_CAMERAS_IN_USE,
|
||||
CameraState.ERROR_CAMERA_IN_USE -> context.toast(R.string.camera_in_use_error, Toast.LENGTH_LONG)
|
||||
CameraState.ERROR_CAMERA_IN_USE -> context.toast(
|
||||
id = R.string.camera_in_use_error,
|
||||
length = Toast.LENGTH_LONG
|
||||
)
|
||||
|
||||
CameraState.ERROR_CAMERA_FATAL_ERROR -> context.toast(R.string.camera_unavailable)
|
||||
CameraState.ERROR_STREAM_CONFIG -> context.toast(R.string.camera_configure_error)
|
||||
CameraState.ERROR_CAMERA_DISABLED -> context.toast(R.string.camera_disabled_by_admin_error)
|
||||
CameraState.ERROR_DO_NOT_DISTURB_MODE_ENABLED -> context.toast(R.string.camera_dnd_error, Toast.LENGTH_LONG)
|
||||
CameraState.ERROR_DO_NOT_DISTURB_MODE_ENABLED -> context.toast(
|
||||
id = R.string.camera_dnd_error,
|
||||
length = Toast.LENGTH_LONG
|
||||
)
|
||||
|
||||
CameraState.ERROR_OTHER_RECOVERABLE_ERROR -> {}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import androidx.camera.core.CameraSelector
|
||||
import com.simplemobiletools.camera.models.CaptureMode
|
||||
import com.simplemobiletools.camera.models.TimerMode
|
||||
import com.simplemobiletools.commons.helpers.BaseConfig
|
||||
import org.fossify.camera.models.CaptureMode
|
||||
import org.fossify.camera.models.TimerMode
|
||||
import org.fossify.commons.helpers.BaseConfig
|
||||
import java.io.File
|
||||
|
||||
class Config(context: Context) : BaseConfig(context) {
|
||||
@@ -15,9 +15,13 @@ class Config(context: Context) : BaseConfig(context) {
|
||||
|
||||
var savePhotosFolder: String
|
||||
get(): String {
|
||||
var path = prefs.getString(SAVE_PHOTOS, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString())
|
||||
var path = prefs.getString(
|
||||
SAVE_PHOTOS,
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
|
||||
)
|
||||
if (!File(path).exists() || !File(path).isDirectory) {
|
||||
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
|
||||
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
|
||||
.toString()
|
||||
savePhotosFolder = path
|
||||
}
|
||||
return path!!
|
||||
@@ -30,7 +34,8 @@ class Config(context: Context) : BaseConfig(context) {
|
||||
|
||||
var volumeButtonsAsShutter: Boolean
|
||||
get() = prefs.getBoolean(VOLUME_BUTTONS_AS_SHUTTER, false)
|
||||
set(volumeButtonsAsShutter) = prefs.edit().putBoolean(VOLUME_BUTTONS_AS_SHUTTER, volumeButtonsAsShutter).apply()
|
||||
set(volumeButtonsAsShutter) = prefs.edit()
|
||||
.putBoolean(VOLUME_BUTTONS_AS_SHUTTER, volumeButtonsAsShutter).apply()
|
||||
|
||||
var flipPhotos: Boolean
|
||||
get() = prefs.getBoolean(FLIP_PHOTOS, true)
|
||||
@@ -50,38 +55,48 @@ class Config(context: Context) : BaseConfig(context) {
|
||||
|
||||
var backPhotoResIndex: Int
|
||||
get() = prefs.getInt(BACK_PHOTO_RESOLUTION_INDEX, 0)
|
||||
set(backPhotoResIndex) = prefs.edit().putInt(BACK_PHOTO_RESOLUTION_INDEX, backPhotoResIndex).apply()
|
||||
set(backPhotoResIndex) = prefs.edit().putInt(BACK_PHOTO_RESOLUTION_INDEX, backPhotoResIndex)
|
||||
.apply()
|
||||
|
||||
var backVideoResIndex: Int
|
||||
get() = prefs.getInt(BACK_VIDEO_RESOLUTION_INDEX, 0)
|
||||
set(backVideoResIndex) = prefs.edit().putInt(BACK_VIDEO_RESOLUTION_INDEX, backVideoResIndex).apply()
|
||||
set(backVideoResIndex) = prefs.edit().putInt(BACK_VIDEO_RESOLUTION_INDEX, backVideoResIndex)
|
||||
.apply()
|
||||
|
||||
var frontPhotoResIndex: Int
|
||||
get() = prefs.getInt(FRONT_PHOTO_RESOLUTION_INDEX, 0)
|
||||
set(frontPhotoResIndex) = prefs.edit().putInt(FRONT_PHOTO_RESOLUTION_INDEX, frontPhotoResIndex).apply()
|
||||
set(frontPhotoResIndex) = prefs.edit()
|
||||
.putInt(FRONT_PHOTO_RESOLUTION_INDEX, frontPhotoResIndex).apply()
|
||||
|
||||
var frontVideoResIndex: Int
|
||||
get() = prefs.getInt(FRONT_VIDEO_RESOLUTION_INDEX, 0)
|
||||
set(frontVideoResIndex) = prefs.edit().putInt(FRONT_VIDEO_RESOLUTION_INDEX, frontVideoResIndex).apply()
|
||||
set(frontVideoResIndex) = prefs.edit()
|
||||
.putInt(FRONT_VIDEO_RESOLUTION_INDEX, frontVideoResIndex).apply()
|
||||
|
||||
var savePhotoMetadata: Boolean
|
||||
get() = prefs.getBoolean(SAVE_PHOTO_METADATA, true)
|
||||
set(savePhotoMetadata) = prefs.edit().putBoolean(SAVE_PHOTO_METADATA, savePhotoMetadata).apply()
|
||||
set(savePhotoMetadata) = prefs.edit().putBoolean(SAVE_PHOTO_METADATA, savePhotoMetadata)
|
||||
.apply()
|
||||
|
||||
var savePhotoVideoLocation: Boolean
|
||||
get() = prefs.getBoolean(SAVE_PHOTO_VIDEO_LOCATION, false)
|
||||
set(savePhotoVideoLocation) = prefs.edit().putBoolean(SAVE_PHOTO_VIDEO_LOCATION, savePhotoVideoLocation).apply()
|
||||
set(savePhotoVideoLocation) = prefs.edit()
|
||||
.putBoolean(SAVE_PHOTO_VIDEO_LOCATION, savePhotoVideoLocation).apply()
|
||||
|
||||
var photoQuality: Int
|
||||
get() = prefs.getInt(PHOTO_QUALITY, 80)
|
||||
set(photoQuality) = prefs.edit().putInt(PHOTO_QUALITY, photoQuality).apply()
|
||||
|
||||
var captureMode: CaptureMode
|
||||
get() = CaptureMode.values()[prefs.getInt(CAPTURE_MODE, CaptureMode.MINIMIZE_LATENCY.ordinal)]
|
||||
get() = CaptureMode.values()[prefs.getInt(
|
||||
CAPTURE_MODE,
|
||||
CaptureMode.MINIMIZE_LATENCY.ordinal
|
||||
)]
|
||||
set(captureMode) = prefs.edit().putInt(CAPTURE_MODE, captureMode.ordinal).apply()
|
||||
|
||||
var timerMode: TimerMode
|
||||
get() = TimerMode.values().getOrNull(prefs.getInt(TIMER_MODE, TimerMode.OFF.ordinal)) ?: TimerMode.OFF
|
||||
get() = TimerMode.values().getOrNull(prefs.getInt(TIMER_MODE, TimerMode.OFF.ordinal))
|
||||
?: TimerMode.OFF
|
||||
set(timerMode) = prefs.edit().putInt(TIMER_MODE, timerMode.ordinal).apply()
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
const val ORIENT_PORTRAIT = 0
|
||||
const val ORIENT_LANDSCAPE_LEFT = 1
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers;
|
||||
package org.fossify.camera.helpers;
|
||||
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.ImageFormat
|
||||
@@ -6,14 +6,15 @@ import android.hardware.camera2.CameraCharacteristics
|
||||
import android.hardware.camera2.CameraManager
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.camera.core.CameraSelector
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.models.CameraSelectorImageQualities
|
||||
import com.simplemobiletools.camera.models.MySize
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import org.fossify.camera.extensions.config
|
||||
import org.fossify.camera.models.CameraSelectorImageQualities
|
||||
import org.fossify.camera.models.MySize
|
||||
import org.fossify.commons.extensions.showErrorToast
|
||||
|
||||
class ImageQualityManager(private val activity: AppCompatActivity) {
|
||||
companion object {
|
||||
private val CAMERA_LENS = arrayOf(CameraCharacteristics.LENS_FACING_FRONT, CameraCharacteristics.LENS_FACING_BACK)
|
||||
private val CAMERA_LENS =
|
||||
arrayOf(CameraCharacteristics.LENS_FACING_FRONT, CameraCharacteristics.LENS_FACING_BACK)
|
||||
}
|
||||
|
||||
private val cameraManager = activity.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||
@@ -25,10 +26,14 @@ class ImageQualityManager(private val activity: AppCompatActivity) {
|
||||
for (cameraId in cameraManager.cameraIdList) {
|
||||
try {
|
||||
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
|
||||
val lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING) ?: continue
|
||||
val lensFacing =
|
||||
characteristics.get(CameraCharacteristics.LENS_FACING) ?: continue
|
||||
if (lensFacing in CAMERA_LENS) {
|
||||
val configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue
|
||||
val imageSizes = configMap.getOutputSizes(ImageFormat.JPEG).map { MySize(it.width, it.height) }
|
||||
val configMap =
|
||||
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
|
||||
?: continue
|
||||
val imageSizes = configMap.getOutputSizes(ImageFormat.JPEG)
|
||||
.map { MySize(it.width, it.height) }
|
||||
val cameraSelector = lensFacing.toCameraSelector()
|
||||
imageQualities.add(CameraSelectorImageQualities(cameraSelector, imageSizes))
|
||||
}
|
||||
@@ -50,7 +55,9 @@ class ImageQualityManager(private val activity: AppCompatActivity) {
|
||||
fun getUserSelectedResolution(cameraSelector: CameraSelector): MySize {
|
||||
val resolutions = getSupportedResolutions(cameraSelector)
|
||||
val isFrontCamera = cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA
|
||||
var index = mediaSizeStore.getCurrentSizeIndex(isPhotoCapture = true, isFrontCamera = isFrontCamera)
|
||||
var index = mediaSizeStore.getCurrentSizeIndex(
|
||||
isPhotoCapture = true, isFrontCamera = isFrontCamera
|
||||
)
|
||||
index = index.coerceAtMost(resolutions.lastIndex).coerceAtLeast(0)
|
||||
return resolutions[index]
|
||||
}
|
||||
@@ -61,7 +68,9 @@ class ImageQualityManager(private val activity: AppCompatActivity) {
|
||||
.flatMap { it.qualities }
|
||||
.sortedByDescending { it.pixels }
|
||||
.distinctBy { it.getAspectRatio(activity) }
|
||||
.sortedByDescending { it.getAspectRatio(activity).split(":").firstOrNull()?.toIntOrNull() }
|
||||
.sortedByDescending {
|
||||
it.getAspectRatio(activity).split(":").firstOrNull()?.toIntOrNull()
|
||||
}
|
||||
.filter { it.isSupported(fullScreenSize.isSixteenToNine()) }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ContentResolver
|
||||
@@ -11,13 +11,13 @@ import androidx.camera.core.ImageCaptureException
|
||||
import androidx.camera.core.ImageProxy
|
||||
import androidx.camera.core.internal.compat.workaround.ExifRotationAvailability
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import com.simplemobiletools.camera.helpers.ImageUtil.CodecFailedException
|
||||
import com.simplemobiletools.camera.helpers.ImageUtil.imageToJpegByteArray
|
||||
import com.simplemobiletools.camera.helpers.ImageUtil.jpegImageToJpegByteArray
|
||||
import com.simplemobiletools.camera.models.MediaOutput
|
||||
import com.simplemobiletools.commons.extensions.copyTo
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.commons.helpers.isQPlus
|
||||
import org.fossify.camera.helpers.ImageUtil.CodecFailedException
|
||||
import org.fossify.camera.helpers.ImageUtil.imageToJpegByteArray
|
||||
import org.fossify.camera.helpers.ImageUtil.jpegImageToJpegByteArray
|
||||
import org.fossify.camera.models.MediaOutput
|
||||
import org.fossify.commons.extensions.copyTo
|
||||
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||
import org.fossify.commons.helpers.isQPlus
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
@@ -141,10 +141,12 @@ class ImageSaver private constructor(
|
||||
saveError = SaveError.ENCODE_FAILED
|
||||
errorMessage = "Failed to encode Image"
|
||||
}
|
||||
|
||||
CodecFailedException.FailureType.DECODE_FAILED -> {
|
||||
saveError = SaveError.CROP_FAILED
|
||||
errorMessage = "Failed to crop Image"
|
||||
}
|
||||
|
||||
CodecFailedException.FailureType.UNKNOWN -> {
|
||||
saveError = SaveError.UNKNOWN
|
||||
errorMessage = "Failed to transcode Image"
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.graphics.*
|
||||
import androidx.annotation.IntRange
|
||||
@@ -25,9 +25,15 @@ object ImageUtil {
|
||||
jpegImageToJpegByteArray(image, image.cropRect, jpegQuality)
|
||||
}
|
||||
}
|
||||
|
||||
ImageFormat.YUV_420_888 -> {
|
||||
yuvImageToJpegByteArray(image, if (shouldCropImage) image.cropRect else null, jpegQuality)
|
||||
yuvImageToJpegByteArray(
|
||||
image,
|
||||
if (shouldCropImage) image.cropRect else null,
|
||||
jpegQuality
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
// Unrecognized image format
|
||||
byteArrayOf()
|
||||
@@ -223,7 +229,10 @@ object ImageUtil {
|
||||
/**
|
||||
* Exception for error during transcoding image.
|
||||
*/
|
||||
class CodecFailedException internal constructor(message: String, val failureType: FailureType) : Exception(message) {
|
||||
class CodecFailedException internal constructor(
|
||||
message: String,
|
||||
val failureType: FailureType
|
||||
) : Exception(message) {
|
||||
enum class FailureType {
|
||||
ENCODE_FAILED, DECODE_FAILED, UNKNOWN
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioAttributes
|
||||
@@ -9,7 +9,7 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.annotation.RawRes
|
||||
import com.simplemobiletools.camera.R
|
||||
import org.fossify.camera.R
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@@ -31,7 +31,14 @@ class MediaActionSound(private val context: Context) {
|
||||
private const val STATE_LOADING = 1
|
||||
private const val STATE_LOADING_PLAY_REQUESTED = 2
|
||||
private const val STATE_LOADED = 3
|
||||
private val SOUNDS = arrayOf(SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, STOP_VIDEO_RECORDING, TIMER_COUNTDOWN, TIMER_COUNTDOWN_2_SECONDS)
|
||||
private val SOUNDS = arrayOf(
|
||||
SHUTTER_CLICK,
|
||||
FOCUS_COMPLETE,
|
||||
START_VIDEO_RECORDING,
|
||||
STOP_VIDEO_RECORDING,
|
||||
TIMER_COUNTDOWN,
|
||||
TIMER_COUNTDOWN_2_SECONDS
|
||||
)
|
||||
}
|
||||
|
||||
sealed class MediaSound {
|
||||
@@ -73,7 +80,10 @@ class MediaActionSound(private val context: Context) {
|
||||
if (status != 0) {
|
||||
sound.state = STATE_NOT_LOADED
|
||||
sound.loadId = 0
|
||||
Log.e(TAG, "OnLoadCompleteListener() error: $status loading sound: ${sound.mediaSound}")
|
||||
Log.e(
|
||||
TAG,
|
||||
"OnLoadCompleteListener() error: $status loading sound: ${sound.mediaSound}"
|
||||
)
|
||||
return@OnLoadCompleteListener
|
||||
}
|
||||
when (sound.state) {
|
||||
@@ -83,7 +93,10 @@ class MediaActionSound(private val context: Context) {
|
||||
sound.state = STATE_LOADED
|
||||
}
|
||||
|
||||
else -> Log.e(TAG, "OnLoadCompleteListener() called in wrong state: ${sound.state} for sound: ${sound.mediaSound}")
|
||||
else -> Log.e(
|
||||
TAG,
|
||||
"OnLoadCompleteListener() called in wrong state: ${sound.state} for sound: ${sound.mediaSound}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +142,7 @@ class MediaActionSound(private val context: Context) {
|
||||
}
|
||||
|
||||
fun load(mediaSound: MediaSound) {
|
||||
val sound = sounds.firstOrNull() { it.mediaSound == mediaSound } ?: return
|
||||
val sound = sounds.firstOrNull { it.mediaSound == mediaSound } ?: return
|
||||
synchronized(sound) {
|
||||
when (sound.state) {
|
||||
STATE_NOT_LOADED -> {
|
||||
@@ -170,7 +183,10 @@ class MediaActionSound(private val context: Context) {
|
||||
playWithSoundPool(sound)
|
||||
}
|
||||
|
||||
else -> Log.e(TAG, "play() called in wrong state: ${sound.state} for sound: $mediaSound")
|
||||
else -> Log.e(
|
||||
TAG,
|
||||
"play() called in wrong state: ${sound.state} for sound: $mediaSound"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,7 +203,11 @@ class MediaActionSound(private val context: Context) {
|
||||
private fun getSoundDuration(mediaSound: MediaSound): Long {
|
||||
releaseMediaPlayer()
|
||||
mediaPlayer = when (mediaSound) {
|
||||
is MediaSound.ManufacturerSound -> MediaPlayer.create(context, Uri.fromFile(File(mediaSound.path)))
|
||||
is MediaSound.ManufacturerSound -> MediaPlayer.create(
|
||||
context,
|
||||
Uri.fromFile(File(mediaSound.path))
|
||||
)
|
||||
|
||||
is MediaSound.RawResSound -> MediaPlayer.create(context, mediaSound.resId)
|
||||
}
|
||||
return mediaPlayer!!.duration.toLong()
|
||||
@@ -201,7 +221,10 @@ class MediaActionSound(private val context: Context) {
|
||||
soundPool!!.stop(sound.streamId)
|
||||
}
|
||||
|
||||
else -> Log.w(TAG, "stop() should be called after sound is loaded for sound: $mediaSound")
|
||||
else -> Log.w(
|
||||
TAG,
|
||||
"stop() should be called after sound is loaded for sound: $mediaSound"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.net.Uri
|
||||
@@ -6,15 +6,30 @@ import android.os.Environment
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.provider.DocumentsContract
|
||||
import android.provider.MediaStore
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.extensions.getOutputMediaFileName
|
||||
import com.simplemobiletools.camera.extensions.getOutputMediaFilePath
|
||||
import com.simplemobiletools.camera.extensions.getRandomMediaName
|
||||
import com.simplemobiletools.camera.models.MediaOutput
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.isOreoPlus
|
||||
import com.simplemobiletools.commons.helpers.isQPlus
|
||||
import org.fossify.camera.extensions.config
|
||||
import org.fossify.camera.extensions.getOutputMediaFileName
|
||||
import org.fossify.camera.extensions.getOutputMediaFilePath
|
||||
import org.fossify.camera.extensions.getRandomMediaName
|
||||
import org.fossify.camera.models.MediaOutput
|
||||
import org.fossify.commons.activities.BaseSimpleActivity
|
||||
import org.fossify.commons.extensions.createDocumentUriFromRootTree
|
||||
import org.fossify.commons.extensions.createDocumentUriUsingFirstParentTreeUri
|
||||
import org.fossify.commons.extensions.getAndroidSAFUri
|
||||
import org.fossify.commons.extensions.getDocumentFile
|
||||
import org.fossify.commons.extensions.getDoesFilePathExist
|
||||
import org.fossify.commons.extensions.getFileOutputStreamSync
|
||||
import org.fossify.commons.extensions.getFilenameFromPath
|
||||
import org.fossify.commons.extensions.getMimeType
|
||||
import org.fossify.commons.extensions.getRealPathFromURI
|
||||
import org.fossify.commons.extensions.hasProperStoredAndroidTreeUri
|
||||
import org.fossify.commons.extensions.hasProperStoredFirstParentUri
|
||||
import org.fossify.commons.extensions.hasProperStoredTreeUri
|
||||
import org.fossify.commons.extensions.isAccessibleWithSAFSdk30
|
||||
import org.fossify.commons.extensions.isRestrictedSAFOnlyRoot
|
||||
import org.fossify.commons.extensions.needsStupidWritePermissions
|
||||
import org.fossify.commons.extensions.showErrorToast
|
||||
import org.fossify.commons.helpers.isOreoPlus
|
||||
import org.fossify.commons.helpers.isQPlus
|
||||
import java.io.File
|
||||
import java.io.OutputStream
|
||||
|
||||
@@ -114,7 +129,11 @@ class MediaOutputHelper(
|
||||
if (isQPlus()) {
|
||||
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM)
|
||||
} else {
|
||||
put(MediaStore.MediaColumns.DATA, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString())
|
||||
put(
|
||||
MediaStore.MediaColumns.DATA,
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
|
||||
.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,7 +173,8 @@ class MediaOutputHelper(
|
||||
DocumentsContract.Document.COLUMN_MIME_TYPE,
|
||||
videoFileName
|
||||
) ?: return null
|
||||
val fileDescriptor = contentResolver.openFileDescriptor(documentUri, MODE) ?: return null
|
||||
val fileDescriptor =
|
||||
contentResolver.openFileDescriptor(documentUri, MODE) ?: return null
|
||||
mediaOutput = MediaOutput.FileDescriptorMediaOutput(fileDescriptor, documentUri)
|
||||
}
|
||||
return mediaOutput
|
||||
@@ -216,13 +236,17 @@ class MediaOutputHelper(
|
||||
if (activity.getDoesFilePathExist(path)) {
|
||||
activity.createDocumentUriFromRootTree(path)
|
||||
} else {
|
||||
documentFile.createFile(path.getMimeType(), path.getFilenameFromPath())?.uri
|
||||
documentFile.createFile(
|
||||
path.getMimeType(),
|
||||
path.getFilenameFromPath()
|
||||
)?.uri
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activity.isAccessibleWithSAFSdk30(path) -> {
|
||||
try {
|
||||
activity.createDocumentUriUsingFirstParentTreeUri(path)
|
||||
@@ -230,6 +254,7 @@ class MediaOutputHelper(
|
||||
null
|
||||
} ?: Uri.fromFile(targetFile)
|
||||
}
|
||||
|
||||
else -> return Uri.fromFile(targetFile)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
class MediaSizeStore(private val config: Config) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.content.Context
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
@@ -7,18 +7,33 @@ import android.net.Uri
|
||||
import android.os.AsyncTask
|
||||
import android.os.Environment
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.activities.MainActivity
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.extensions.getOutputMediaFilePath
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import org.fossify.camera.R
|
||||
import org.fossify.camera.activities.MainActivity
|
||||
import org.fossify.camera.extensions.config
|
||||
import org.fossify.camera.extensions.getOutputMediaFilePath
|
||||
import org.fossify.commons.extensions.copyTo
|
||||
import org.fossify.commons.extensions.degreesFromOrientation
|
||||
import org.fossify.commons.extensions.getDocumentFile
|
||||
import org.fossify.commons.extensions.getParentPath
|
||||
import org.fossify.commons.extensions.getSomeDocumentFile
|
||||
import org.fossify.commons.extensions.hasProperStoredTreeUri
|
||||
import org.fossify.commons.extensions.internalStoragePath
|
||||
import org.fossify.commons.extensions.isPathOnOTG
|
||||
import org.fossify.commons.extensions.needsStupidWritePermissions
|
||||
import org.fossify.commons.extensions.saveImageRotation
|
||||
import org.fossify.commons.extensions.showErrorToast
|
||||
import org.fossify.commons.extensions.toast
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileOutputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
class PhotoProcessor(
|
||||
val activity: MainActivity, val saveUri: Uri?, val deviceOrientation: Int, val previewRotation: Int, val isUsingFrontCamera: Boolean,
|
||||
val activity: MainActivity,
|
||||
val saveUri: Uri?,
|
||||
val deviceOrientation: Int,
|
||||
val previewRotation: Int,
|
||||
val isUsingFrontCamera: Boolean,
|
||||
val isThirdPartyIntent: Boolean
|
||||
) :
|
||||
AsyncTask<ByteArray, Void, String>() {
|
||||
@@ -49,12 +64,15 @@ class PhotoProcessor(
|
||||
if (activity.needsStupidWritePermissions(path)) {
|
||||
if (!activity.hasProperStoredTreeUri(activity.isPathOnOTG(path))) {
|
||||
activity.toast(R.string.save_error_internal_storage)
|
||||
activity.config.savePhotosFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
|
||||
activity.config.savePhotosFolder =
|
||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
|
||||
.toString()
|
||||
return ""
|
||||
}
|
||||
|
||||
var document = activity.getDocumentFile(path.getParentPath())
|
||||
document = document?.createFile("", path.substring(path.lastIndexOf('/') + 1)) ?: activity.getDocumentFile(path)
|
||||
document = document?.createFile("", path.substring(path.lastIndexOf('/') + 1))
|
||||
?: activity.getDocumentFile(path)
|
||||
if (document == null) {
|
||||
activity.toast(R.string.save_error_internal_storage)
|
||||
return ""
|
||||
@@ -75,7 +93,10 @@ class PhotoProcessor(
|
||||
null
|
||||
}
|
||||
|
||||
val orient = exif?.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
|
||||
val orient = exif?.getAttributeInt(
|
||||
ExifInterface.TAG_ORIENTATION,
|
||||
ExifInterface.ORIENTATION_UNDEFINED
|
||||
)
|
||||
?: ExifInterface.ORIENTATION_UNDEFINED
|
||||
|
||||
val imageRot = orient.degreesFromOrientation()
|
||||
@@ -96,9 +117,17 @@ class PhotoProcessor(
|
||||
matrix.preScale(if (isPortrait) -1f else 1f, if (isPortrait) 1f else -1f)
|
||||
|
||||
try {
|
||||
image = Bitmap.createBitmap(image, 0, 0, image.width, image.height, matrix, false)
|
||||
image = Bitmap.createBitmap(
|
||||
image,
|
||||
0,
|
||||
0,
|
||||
image.width,
|
||||
image.height,
|
||||
matrix,
|
||||
false
|
||||
)
|
||||
} catch (e: OutOfMemoryError) {
|
||||
activity.toast(com.simplemobiletools.commons.R.string.out_of_memory_error)
|
||||
activity.toast(org.fossify.commons.R.string.out_of_memory_error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,7 +150,8 @@ class PhotoProcessor(
|
||||
} else {
|
||||
val documentFile = activity.getSomeDocumentFile(path)
|
||||
if (documentFile != null) {
|
||||
val parcelFileDescriptor = activity.contentResolver.openFileDescriptor(documentFile.uri, "rw")
|
||||
val parcelFileDescriptor =
|
||||
activity.contentResolver.openFileDescriptor(documentFile.uri, "rw")
|
||||
val fileDescriptor = parcelFileDescriptor!!.fileDescriptor
|
||||
ExifInterface(fileDescriptor)
|
||||
} else {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.view.ScaleGestureDetector
|
||||
import androidx.camera.core.CameraControl
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import android.Manifest
|
||||
import android.location.Location
|
||||
import android.location.LocationListener
|
||||
import android.location.LocationManager
|
||||
import androidx.annotation.RequiresPermission
|
||||
import com.simplemobiletools.camera.extensions.checkLocationPermission
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import org.fossify.camera.extensions.checkLocationPermission
|
||||
import org.fossify.commons.activities.BaseSimpleActivity
|
||||
|
||||
class SimpleLocationManager(private val activity: BaseSimpleActivity) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.camera.video.Quality
|
||||
import androidx.camera.video.QualitySelector
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.camera.extensions.toVideoQuality
|
||||
import com.simplemobiletools.camera.models.CameraSelectorVideoQualities
|
||||
import com.simplemobiletools.camera.models.VideoQuality
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import org.fossify.camera.extensions.config
|
||||
import org.fossify.camera.extensions.toVideoQuality
|
||||
import org.fossify.camera.models.CameraSelectorVideoQualities
|
||||
import org.fossify.camera.models.VideoQuality
|
||||
import org.fossify.commons.extensions.showErrorToast
|
||||
|
||||
class VideoQualityManager(
|
||||
private val activity: AppCompatActivity,
|
||||
) {
|
||||
companion object {
|
||||
private val QUALITIES = listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD)
|
||||
private val CAMERA_SELECTORS = arrayOf(CameraSelector.DEFAULT_BACK_CAMERA, CameraSelector.DEFAULT_FRONT_CAMERA)
|
||||
private val CAMERA_SELECTORS =
|
||||
arrayOf(CameraSelector.DEFAULT_BACK_CAMERA, CameraSelector.DEFAULT_FRONT_CAMERA)
|
||||
}
|
||||
|
||||
private val videoQualities = mutableListOf<CameraSelectorVideoQualities>()
|
||||
@@ -33,7 +34,12 @@ class VideoQualityManager(
|
||||
.filter(QUALITIES::contains)
|
||||
.also { allQualities ->
|
||||
val qualities = allQualities.map { it.toVideoQuality() }
|
||||
videoQualities.add(CameraSelectorVideoQualities(camSelector, qualities))
|
||||
videoQualities.add(
|
||||
CameraSelectorVideoQualities(
|
||||
camSelector,
|
||||
qualities
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@@ -45,7 +51,10 @@ class VideoQualityManager(
|
||||
|
||||
fun getUserSelectedQuality(cameraSelector: CameraSelector): VideoQuality {
|
||||
val isFrontCamera = cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA
|
||||
val selectionIndex = mediaSizeStore.getCurrentSizeIndex(isPhotoCapture = false, isFrontCamera = isFrontCamera).coerceAtLeast(0)
|
||||
val selectionIndex = mediaSizeStore.getCurrentSizeIndex(
|
||||
isPhotoCapture = false,
|
||||
isFrontCamera = isFrontCamera
|
||||
).coerceAtLeast(0)
|
||||
return getSupportedQualities(cameraSelector).getOrElse(selectionIndex) { VideoQuality.HD }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.helpers
|
||||
package org.fossify.camera.helpers
|
||||
|
||||
import androidx.camera.core.ZoomState
|
||||
|
||||
@@ -7,7 +7,8 @@ class ZoomCalculator {
|
||||
fun calculateZoomRatio(zoomState: ZoomState, pinchToZoomScale: Float): Float {
|
||||
val clampedRatio = zoomState.zoomRatio * speedUpZoomBy2X(pinchToZoomScale)
|
||||
// Clamp the ratio with the zoom range.
|
||||
return clampedRatio.coerceAtLeast(zoomState.minZoomRatio).coerceAtMost(zoomState.maxZoomRatio)
|
||||
return clampedRatio.coerceAtLeast(zoomState.minZoomRatio)
|
||||
.coerceAtMost(zoomState.maxZoomRatio)
|
||||
}
|
||||
|
||||
private fun speedUpZoomBy2X(scaleFactor: Float): Float {
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.simplemobiletools.camera.implementations
|
||||
package org.fossify.camera.implementations
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.camera.view.PreviewView
|
||||
import com.simplemobiletools.camera.helpers.CameraErrorHandler
|
||||
import com.simplemobiletools.camera.helpers.MediaOutputHelper
|
||||
import com.simplemobiletools.camera.helpers.MediaSoundHelper
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import org.fossify.camera.helpers.CameraErrorHandler
|
||||
import org.fossify.camera.helpers.MediaOutputHelper
|
||||
import org.fossify.camera.helpers.MediaSoundHelper
|
||||
import org.fossify.commons.activities.BaseSimpleActivity
|
||||
|
||||
class CameraXInitializer(private val activity: BaseSimpleActivity) {
|
||||
|
||||
@@ -18,7 +18,8 @@ class CameraXInitializer(private val activity: BaseSimpleActivity) {
|
||||
initInPhotoMode: Boolean,
|
||||
): CameraXPreview {
|
||||
val cameraErrorHandler = newCameraErrorHandler()
|
||||
val mediaOutputHelper = newMediaOutputHelper(cameraErrorHandler, outputUri, isThirdPartyIntent)
|
||||
val mediaOutputHelper =
|
||||
newMediaOutputHelper(cameraErrorHandler, outputUri, isThirdPartyIntent)
|
||||
return CameraXPreview(
|
||||
activity,
|
||||
previewView,
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.implementations
|
||||
package org.fossify.camera.implementations
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
@@ -8,13 +8,45 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Rational
|
||||
import android.util.Size
|
||||
import android.view.*
|
||||
import android.view.Display
|
||||
import android.view.GestureDetector
|
||||
import android.view.GestureDetector.SimpleOnGestureListener
|
||||
import androidx.camera.core.*
|
||||
import androidx.camera.core.ImageCapture.*
|
||||
import android.view.MotionEvent
|
||||
import android.view.OrientationEventListener
|
||||
import android.view.ScaleGestureDetector
|
||||
import android.view.Surface
|
||||
import androidx.camera.core.Camera
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.CameraState
|
||||
import androidx.camera.core.DisplayOrientedMeteringPointFactory
|
||||
import androidx.camera.core.FocusMeteringAction
|
||||
import androidx.camera.core.ImageCapture
|
||||
import androidx.camera.core.ImageCapture.Builder
|
||||
import androidx.camera.core.ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY
|
||||
import androidx.camera.core.ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY
|
||||
import androidx.camera.core.ImageCapture.ERROR_CAPTURE_FAILED
|
||||
import androidx.camera.core.ImageCapture.FLASH_MODE_AUTO
|
||||
import androidx.camera.core.ImageCapture.FLASH_MODE_OFF
|
||||
import androidx.camera.core.ImageCapture.FLASH_MODE_ON
|
||||
import androidx.camera.core.ImageCapture.Metadata
|
||||
import androidx.camera.core.ImageCapture.OnImageCapturedCallback
|
||||
import androidx.camera.core.ImageCaptureException
|
||||
import androidx.camera.core.ImageProxy
|
||||
import androidx.camera.core.Preview
|
||||
import androidx.camera.core.UseCase
|
||||
import androidx.camera.core.UseCaseGroup
|
||||
import androidx.camera.core.ViewPort
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.camera.video.*
|
||||
import androidx.camera.video.FallbackStrategy
|
||||
import androidx.camera.video.FileDescriptorOutputOptions
|
||||
import androidx.camera.video.FileOutputOptions
|
||||
import androidx.camera.video.MediaStoreOutputOptions
|
||||
import androidx.camera.video.Quality
|
||||
import androidx.camera.video.QualitySelector
|
||||
import androidx.camera.video.Recorder
|
||||
import androidx.camera.video.Recording
|
||||
import androidx.camera.video.VideoCapture
|
||||
import androidx.camera.video.VideoRecordEvent
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.camera.view.PreviewView.ScaleType
|
||||
import androidx.core.content.ContextCompat
|
||||
@@ -24,18 +56,36 @@ import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.window.layout.WindowMetricsCalculator
|
||||
import com.bumptech.glide.load.ImageHeaderParser.UNKNOWN_ORIENTATION
|
||||
import com.simplemobiletools.camera.R
|
||||
import com.simplemobiletools.camera.extensions.*
|
||||
import com.simplemobiletools.camera.helpers.*
|
||||
import com.simplemobiletools.camera.interfaces.MyPreview
|
||||
import com.simplemobiletools.camera.models.CaptureMode
|
||||
import com.simplemobiletools.camera.models.MediaOutput
|
||||
import com.simplemobiletools.camera.models.MySize
|
||||
import com.simplemobiletools.camera.models.ResolutionOption
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_ACCESS_FINE_LOCATION
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import org.fossify.camera.R
|
||||
import org.fossify.camera.extensions.checkLocationPermission
|
||||
import org.fossify.camera.extensions.config
|
||||
import org.fossify.camera.extensions.toAppFlashMode
|
||||
import org.fossify.camera.extensions.toCameraSelector
|
||||
import org.fossify.camera.extensions.toCameraXFlashMode
|
||||
import org.fossify.camera.extensions.toCameraXQuality
|
||||
import org.fossify.camera.extensions.toLensFacing
|
||||
import org.fossify.camera.helpers.BitmapUtils
|
||||
import org.fossify.camera.helpers.CameraErrorHandler
|
||||
import org.fossify.camera.helpers.FLASH_ALWAYS_ON
|
||||
import org.fossify.camera.helpers.FLASH_ON
|
||||
import org.fossify.camera.helpers.ImageQualityManager
|
||||
import org.fossify.camera.helpers.ImageSaver
|
||||
import org.fossify.camera.helpers.ImageUtil
|
||||
import org.fossify.camera.helpers.MediaOutputHelper
|
||||
import org.fossify.camera.helpers.MediaSizeStore
|
||||
import org.fossify.camera.helpers.MediaSoundHelper
|
||||
import org.fossify.camera.helpers.PinchToZoomOnScaleGestureListener
|
||||
import org.fossify.camera.helpers.SimpleLocationManager
|
||||
import org.fossify.camera.helpers.VideoQualityManager
|
||||
import org.fossify.camera.interfaces.MyPreview
|
||||
import org.fossify.camera.models.CaptureMode
|
||||
import org.fossify.camera.models.MediaOutput
|
||||
import org.fossify.camera.models.MySize
|
||||
import org.fossify.camera.models.ResolutionOption
|
||||
import org.fossify.commons.activities.BaseSimpleActivity
|
||||
import org.fossify.commons.extensions.toast
|
||||
import org.fossify.commons.helpers.PERMISSION_ACCESS_FINE_LOCATION
|
||||
import org.fossify.commons.helpers.ensureBackgroundThread
|
||||
|
||||
class CameraXPreview(
|
||||
private val activity: BaseSimpleActivity,
|
||||
@@ -58,34 +108,36 @@ class CameraXPreview(
|
||||
private val config = activity.config
|
||||
private val contentResolver = activity.contentResolver
|
||||
private val mainExecutor = ContextCompat.getMainExecutor(activity)
|
||||
private val displayManager = activity.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||
private val displayManager =
|
||||
activity.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
|
||||
private val windowMetricsCalculator = WindowMetricsCalculator.getOrCreate()
|
||||
private val videoQualityManager = VideoQualityManager(activity)
|
||||
private val imageQualityManager = ImageQualityManager(activity)
|
||||
private val mediaSizeStore = MediaSizeStore(config)
|
||||
|
||||
private val orientationEventListener = object : OrientationEventListener(activity, SensorManager.SENSOR_DELAY_NORMAL) {
|
||||
@SuppressLint("RestrictedApi")
|
||||
override fun onOrientationChanged(orientation: Int) {
|
||||
if (orientation == UNKNOWN_ORIENTATION) {
|
||||
return
|
||||
}
|
||||
private val orientationEventListener =
|
||||
object : OrientationEventListener(activity, SensorManager.SENSOR_DELAY_NORMAL) {
|
||||
@SuppressLint("RestrictedApi")
|
||||
override fun onOrientationChanged(orientation: Int) {
|
||||
if (orientation == UNKNOWN_ORIENTATION) {
|
||||
return
|
||||
}
|
||||
|
||||
val rotation = when (orientation) {
|
||||
in 45 until 135 -> Surface.ROTATION_270
|
||||
in 135 until 225 -> Surface.ROTATION_180
|
||||
in 225 until 315 -> Surface.ROTATION_90
|
||||
else -> Surface.ROTATION_0
|
||||
}
|
||||
val rotation = when (orientation) {
|
||||
in 45 until 135 -> Surface.ROTATION_270
|
||||
in 135 until 225 -> Surface.ROTATION_180
|
||||
in 225 until 315 -> Surface.ROTATION_90
|
||||
else -> Surface.ROTATION_0
|
||||
}
|
||||
|
||||
if (lastRotation != rotation) {
|
||||
preview?.targetRotation = rotation
|
||||
imageCapture?.targetRotation = rotation
|
||||
videoCapture?.targetRotation = rotation
|
||||
lastRotation = rotation
|
||||
if (lastRotation != rotation) {
|
||||
preview?.targetRotation = rotation
|
||||
imageCapture?.targetRotation = rotation
|
||||
videoCapture?.targetRotation = rotation
|
||||
lastRotation = rotation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private val cameraHandler = Handler(Looper.getMainLooper())
|
||||
private val photoModeRunnable = Runnable {
|
||||
if (imageCapture == null) {
|
||||
@@ -143,14 +195,16 @@ class CameraXPreview(
|
||||
bindCameraUseCases()
|
||||
setupCameraObservers()
|
||||
} catch (e: Exception) {
|
||||
val errorMessage = if (switching) R.string.camera_switch_error else R.string.camera_open_error
|
||||
val errorMessage =
|
||||
if (switching) R.string.camera_switch_error else R.string.camera_open_error
|
||||
activity.toast(errorMessage)
|
||||
}
|
||||
}, mainExecutor)
|
||||
}
|
||||
|
||||
private fun bindCameraUseCases() {
|
||||
val cameraProvider = cameraProvider ?: throw IllegalStateException("Camera initialization failed.")
|
||||
val cameraProvider =
|
||||
cameraProvider ?: throw IllegalStateException("Camera initialization failed.")
|
||||
|
||||
val resolution = if (isPhotoCapture) {
|
||||
imageQualityManager.getUserSelectedResolution(cameraSelector).also {
|
||||
@@ -281,6 +335,7 @@ class CameraXPreview(
|
||||
listener.setHasFrontAndBackCamera(hasFrontCamera() && hasBackCamera())
|
||||
listener.setCameraAvailable(true)
|
||||
}
|
||||
|
||||
CameraState.Type.PENDING_OPEN,
|
||||
CameraState.Type.CLOSING,
|
||||
CameraState.Type.CLOSED -> {
|
||||
@@ -309,7 +364,12 @@ class CameraXPreview(
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
// source: https://stackoverflow.com/a/60095886/10552591
|
||||
private fun setupZoomAndFocus() {
|
||||
val scaleGesture = camera?.let { ScaleGestureDetector(activity, PinchToZoomOnScaleGestureListener(it.cameraInfo, it.cameraControl)) }
|
||||
val scaleGesture = camera?.let {
|
||||
ScaleGestureDetector(
|
||||
activity,
|
||||
PinchToZoomOnScaleGestureListener(it.cameraInfo, it.cameraControl)
|
||||
)
|
||||
}
|
||||
val gestureDetector = GestureDetector(activity, object : SimpleOnGestureListener() {
|
||||
override fun onDown(event: MotionEvent): Boolean {
|
||||
listener.onTouchPreview()
|
||||
@@ -326,10 +386,11 @@ class CameraXPreview(
|
||||
val yPos = event.y
|
||||
val autoFocusPoint = factory.createPoint(xPos, yPos, AF_SIZE)
|
||||
val autoExposurePoint = factory.createPoint(xPos, yPos, AE_SIZE)
|
||||
val focusMeteringAction = FocusMeteringAction.Builder(autoFocusPoint, FocusMeteringAction.FLAG_AF)
|
||||
.addPoint(autoExposurePoint, FocusMeteringAction.FLAG_AE)
|
||||
.disableAutoCancel()
|
||||
.build()
|
||||
val focusMeteringAction =
|
||||
FocusMeteringAction.Builder(autoFocusPoint, FocusMeteringAction.FLAG_AF)
|
||||
.addPoint(autoExposurePoint, FocusMeteringAction.FLAG_AE)
|
||||
.disableAutoCancel()
|
||||
.build()
|
||||
camera?.cameraControl?.startFocusAndMetering(focusMeteringAction)
|
||||
listener.onFocusCamera(event.rawX, event.rawY)
|
||||
true
|
||||
@@ -399,9 +460,11 @@ class CameraXPreview(
|
||||
}
|
||||
|
||||
val resolutions = if (isPhotoCapture) {
|
||||
imageQualityManager.getSupportedResolutions(cameraSelector).map { it.toResolutionOption() }
|
||||
imageQualityManager.getSupportedResolutions(cameraSelector)
|
||||
.map { it.toResolutionOption() }
|
||||
} else {
|
||||
videoQualityManager.getSupportedQualities(cameraSelector).map { it.toResolutionOption() }
|
||||
videoQualityManager.getSupportedQualities(cameraSelector)
|
||||
.map { it.toResolutionOption() }
|
||||
}
|
||||
|
||||
if (resolutions.size > 2) {
|
||||
@@ -424,7 +487,8 @@ class CameraXPreview(
|
||||
|
||||
private fun toggleResolutions(resolutions: List<ResolutionOption>) {
|
||||
if (resolutions.size >= 2) {
|
||||
val currentIndex = mediaSizeStore.getCurrentSizeIndex(isPhotoCapture, isFrontCameraInUse())
|
||||
val currentIndex =
|
||||
mediaSizeStore.getCurrentSizeIndex(isPhotoCapture, isFrontCameraInUse())
|
||||
|
||||
val nextIndex = if (currentIndex >= resolutions.lastIndex) {
|
||||
0
|
||||
@@ -611,6 +675,7 @@ class CameraXPreview(
|
||||
}
|
||||
}.build().let { videoCapture!!.output.prepareRecording(activity, it) }
|
||||
}
|
||||
|
||||
is MediaOutput.FileMediaOutput -> {
|
||||
FileOutputOptions.Builder(mediaOutput.file).apply {
|
||||
if (config.savePhotoVideoLocation) {
|
||||
@@ -618,6 +683,7 @@ class CameraXPreview(
|
||||
}
|
||||
}.build().let { videoCapture!!.output.prepareRecording(activity, it) }
|
||||
}
|
||||
|
||||
is MediaOutput.MediaStoreOutput -> {
|
||||
MediaStoreOutputOptions.Builder(contentResolver, mediaOutput.contentUri).apply {
|
||||
setContentValues(mediaOutput.contentValues)
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.simplemobiletools.camera.implementations
|
||||
package org.fossify.camera.implementations
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import com.simplemobiletools.camera.models.ResolutionOption
|
||||
import org.fossify.camera.models.ResolutionOption
|
||||
|
||||
interface CameraXPreviewListener {
|
||||
fun onInitPhotoMode()
|
||||
@@ -30,6 +30,7 @@ interface CameraXPreviewListener {
|
||||
isFrontCamera: Boolean,
|
||||
onSelect: (index: Int, changed: Boolean) -> Unit,
|
||||
)
|
||||
|
||||
fun showFlashOptions(photoCapture: Boolean)
|
||||
fun adjustPreviewView(requiresCentering: Boolean)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.interfaces
|
||||
package org.fossify.camera.interfaces
|
||||
|
||||
interface MyPreview {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
package org.fossify.camera.models
|
||||
|
||||
import androidx.camera.core.CameraSelector
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
package org.fossify.camera.models
|
||||
|
||||
import androidx.camera.core.CameraSelector
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
package org.fossify.camera.models
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import com.simplemobiletools.camera.R
|
||||
import org.fossify.camera.R
|
||||
|
||||
enum class CaptureMode(@StringRes val stringResId: Int) {
|
||||
MINIMIZE_LATENCY(R.string.minimize_latency),
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
package org.fossify.camera.models
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.net.Uri
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
package org.fossify.camera.models
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.IdRes
|
||||
import com.simplemobiletools.camera.R
|
||||
import org.fossify.camera.R
|
||||
|
||||
data class MySize(val width: Int, val height: Int, val isFullScreen: Boolean = false) {
|
||||
companion object {
|
||||
@@ -63,7 +63,7 @@ data class MySize(val width: Int, val height: Int, val isFullScreen: Boolean = f
|
||||
isNineteenToEight() -> "19:8"
|
||||
isSquare() -> "1:1"
|
||||
isTwoToOne() -> "2:1"
|
||||
else -> context.resources.getString(com.simplemobiletools.commons.R.string.other)
|
||||
else -> context.resources.getString(org.fossify.commons.R.string.other)
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
package org.fossify.camera.models
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.IdRes
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
package org.fossify.camera.models
|
||||
|
||||
import com.simplemobiletools.camera.R
|
||||
import org.fossify.camera.R
|
||||
|
||||
enum class TimerMode(val millisInFuture: Long) {
|
||||
OFF(0),
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.simplemobiletools.camera.models
|
||||
package org.fossify.camera.models
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.IdRes
|
||||
import com.simplemobiletools.camera.R
|
||||
import org.fossify.camera.R
|
||||
|
||||
enum class VideoQuality(val width: Int, val height: Int) {
|
||||
UHD(3840, 2160),
|
||||
@@ -13,7 +13,8 @@ enum class VideoQuality(val width: Int, val height: Int) {
|
||||
|
||||
val pixels: Int = width * height
|
||||
|
||||
val megaPixels: String = String.format("%.1f", (width * height.toFloat()) / VideoQuality.ONE_MEGA_PIXEL)
|
||||
val megaPixels: String =
|
||||
String.format("%.1f", (width * height.toFloat()) / VideoQuality.ONE_MEGA_PIXEL)
|
||||
|
||||
val ratio = width / height.toFloat()
|
||||
|
||||
@@ -51,7 +52,7 @@ enum class VideoQuality(val width: Int, val height: Int) {
|
||||
isNineteenToEight() -> "19:8"
|
||||
isSquare() -> "1:1"
|
||||
isTwoToOne() -> "2:1"
|
||||
else -> context.resources.getString(com.simplemobiletools.commons.R.string.other)
|
||||
else -> context.resources.getString(org.fossify.commons.R.string.other)
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.simplemobiletools.camera.receivers
|
||||
package org.fossify.camera.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.simplemobiletools.camera.activities.MainActivity
|
||||
import org.fossify.camera.activities.MainActivity
|
||||
|
||||
class HardwareShutterReceiver : BroadcastReceiver() {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.simplemobiletools.camera.views
|
||||
package org.fossify.camera.views
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.os.Handler
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.camera.extensions.config
|
||||
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
|
||||
import org.fossify.commons.extensions.getProperPrimaryColor
|
||||
|
||||
class FocusCircleView(context: Context) : ViewGroup(context) {
|
||||
private val CIRCLE_RADIUS = 50f
|
||||
@@ -1,17 +1,25 @@
|
||||
package com.simplemobiletools.camera.views
|
||||
package org.fossify.camera.views
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.*
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BlurMaskFilter
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.ColorFilter
|
||||
import android.graphics.Paint
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.simplemobiletools.camera.R
|
||||
import org.fossify.camera.R
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class ShadowDrawable(context: Context, private val drawable: Drawable, @StyleRes styleResId: Int) : Drawable() {
|
||||
class ShadowDrawable(context: Context, private val drawable: Drawable, @StyleRes styleResId: Int) :
|
||||
Drawable() {
|
||||
|
||||
companion object {
|
||||
private const val SHARED_BITMAP_BUFFER_SIZE = 640
|
||||
@@ -63,12 +71,23 @@ class ShadowDrawable(context: Context, private val drawable: Drawable, @StyleRes
|
||||
}
|
||||
}
|
||||
if (styleResId != 0) {
|
||||
val obtainStyledAttributes = context.obtainStyledAttributes(styleResId, R.styleable.ShadowDrawable)
|
||||
val obtainStyledAttributes =
|
||||
context.obtainStyledAttributes(styleResId, R.styleable.ShadowDrawable)
|
||||
shadowColor =
|
||||
obtainStyledAttributes.getColor(R.styleable.ShadowDrawable_android_shadowColor, ContextCompat.getColor(context, com.simplemobiletools.commons.R.color.md_grey_400_dark))
|
||||
shadowDx = obtainStyledAttributes.getFloat(R.styleable.ShadowDrawable_android_shadowDx, 0f).toInt()
|
||||
shadowDy = obtainStyledAttributes.getFloat(R.styleable.ShadowDrawable_android_shadowDy, 0f).toInt()
|
||||
val shadowRadius = obtainStyledAttributes.getFloat(R.styleable.ShadowDrawable_android_shadowRadius, 0.0f).coerceAtLeast(0.0f)
|
||||
obtainStyledAttributes.getColor(
|
||||
R.styleable.ShadowDrawable_android_shadowColor,
|
||||
ContextCompat.getColor(context, org.fossify.commons.R.color.md_grey_400_dark)
|
||||
)
|
||||
shadowDx =
|
||||
obtainStyledAttributes.getFloat(R.styleable.ShadowDrawable_android_shadowDx, 0f)
|
||||
.toInt()
|
||||
shadowDy =
|
||||
obtainStyledAttributes.getFloat(R.styleable.ShadowDrawable_android_shadowDy, 0f)
|
||||
.toInt()
|
||||
val shadowRadius = obtainStyledAttributes.getFloat(
|
||||
R.styleable.ShadowDrawable_android_shadowRadius,
|
||||
0.0f
|
||||
).coerceAtLeast(0.0f)
|
||||
shadowRadiusCeiling = ceil(shadowRadius).toInt()
|
||||
val alpha = Color.alpha(shadowColor)
|
||||
if (shadowRadius > 0.0f && alpha > 0) {
|
||||
@@ -103,9 +122,13 @@ class ShadowDrawable(context: Context, private val drawable: Drawable, @StyleRes
|
||||
if (sharedBitmap != null) {
|
||||
sharedBitmap.eraseColor(0)
|
||||
} else {
|
||||
sharedBitmap = Bitmap.createBitmap(SHARED_BITMAP_BUFFER_SIZE, SHARED_BITMAP_BUFFER_SIZE, Bitmap.Config.ARGB_8888)
|
||||
sharedBitmap = Bitmap.createBitmap(
|
||||
SHARED_BITMAP_BUFFER_SIZE,
|
||||
SHARED_BITMAP_BUFFER_SIZE,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
sharedDrawableBitmapBuffer.set(sharedBitmap)
|
||||
sharedDrawableCanvasBuffer.set(Canvas(sharedBitmap!!))
|
||||
sharedDrawableCanvasBuffer.set(Canvas(sharedBitmap))
|
||||
}
|
||||
createBitmap = sharedBitmap
|
||||
canvas2 = sharedDrawableCanvasBuffer.get()!!
|
||||
@@ -150,10 +173,13 @@ class ShadowDrawable(context: Context, private val drawable: Drawable, @StyleRes
|
||||
outputBufferCanvas!!.drawBitmap(createBitmap, srcRect, destRect, bitmapPaint)
|
||||
srcRect[0, 0, unionBounds.width()] = unionBounds.height()
|
||||
destRect.set(unionBounds)
|
||||
canvas.drawBitmap(outputBuffer!!, srcRect, destRect, bitmapPaint)
|
||||
canvas.drawBitmap(outputBuffer, srcRect, destRect, bitmapPaint)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java", ReplaceWith("PixelFormat.TRANSLUCENT", "android.graphics.PixelFormat"))
|
||||
@Deprecated(
|
||||
"Deprecated in Java",
|
||||
ReplaceWith("PixelFormat.TRANSLUCENT", "android.graphics.PixelFormat")
|
||||
)
|
||||
override fun getOpacity(): Int {
|
||||
return drawable.opacity
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m70.19,38.5c1.89,1.89 3.43,4.12 4.55,6.61l-23.61,0 7.38,-12.79c1.55,0.26 3.01,0.77 4.47,1.37 2.75,1.12 5.15,2.75 7.21,4.81z"/>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m45.63,33.69c2.75,-1.2 5.67,-1.72 8.76,-1.72 0.77,0 1.46,0 2.23,0.09L44.77,52.41 37.39,39.62c0.34,-0.43 0.69,-0.77 1.12,-1.2 2.06,-1.98 4.47,-3.61 7.13,-4.72z"/>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m33.7,45.63c0.69,-1.55 1.46,-3.01 2.49,-4.38l11.76,20.44 -14.77,0c-0.86,-2.32 -1.2,-4.81 -1.2,-7.38 -0.09,-3.01 0.52,-5.93 1.72,-8.67z"/>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m38.51,70.19c-1.89,-1.89 -3.43,-4.12 -4.55,-6.61l15.28,0 0,0 8.5,0L50.27,76.37C48.64,76.11 47.09,75.6 45.63,74.99 42.97,73.79 40.57,72.16 38.51,70.19Z"/>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m63.07,74.91c-2.75,1.2 -5.67,1.72 -8.76,1.72 -0.69,0 -1.37,0 -2.06,-0.09l7.56,-13.05 0,0 4.21,-7.38 7.3,12.62c-0.43,0.43 -0.77,0.94 -1.2,1.37 -1.98,2.06 -4.38,3.69 -7.04,4.81z"/>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m74.92,63.06c-0.6,1.46 -1.37,2.92 -2.32,4.21L60.92,46.92l14.6,0c0.86,2.32 1.2,4.81 1.2,7.38 0,3.01 -0.6,5.93 -1.8,8.76z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="m261.5,223q-3.03,0 -4.68,-2.75 -1.65,-2.75 0,-5.5l32.17,-55.83q2.2,-3.58 5.5,-4.26 3.3,-0.69 7.15,1.24 18.98,8.53 33.55,23.79 14.58,15.26 22.55,34.51 1.38,3.58 -0.41,6.19 -1.79,2.61 -5.64,2.61zM222.18,236.47 L189.18,179.27q-2.2,-3.58 -1.1,-7.15 1.1,-3.58 4.4,-5.78 13.2,-9.35 29.29,-14.85 16.09,-5.5 34.24,-5.5 4.13,0 9.07,0.41 4.95,0.41 8.25,0.96 3.85,0.55 5.09,3.3 1.24,2.75 -0.69,6.05l-45.92,79.75q-1.65,2.75 -4.81,2.75 -3.16,0 -4.81,-2.75zM155.35,278q-3.03,0 -5.5,-2.06 -2.48,-2.06 -3.03,-5.09 -0.55,-3.03 -0.69,-6.6 -0.14,-3.58 -0.14,-8.25 0,-17.33 5.64,-34.51Q157.27,204.3 169.1,188.9q3.03,-3.85 7.01,-3.85 3.99,0 6.19,4.13l46.2,80.58q1.65,2.75 -0.14,5.5 -1.79,2.75 -4.81,2.75zM210.35,356.1q-18.15,-8.8 -33.28,-23.93 -15.13,-15.13 -22.83,-34.38 -1.38,-3.58 0.55,-6.19 1.93,-2.61 5.78,-2.61l89.65,0q3.03,0 4.68,2.75 1.65,2.75 0,5.5l-31.63,55.28q-2.2,3.58 -5.5,4.68 -3.3,1.1 -7.43,-1.1zM256,366q-3.85,0 -8.66,-0.41Q242.53,365.17 238.95,364.63q-3.85,-0.55 -5.22,-3.3 -1.38,-2.75 0.55,-6.05l45.38,-79.2q1.65,-2.75 5.5,-2.75 3.85,0 5.5,2.75l32.45,56.38q1.93,3.03 1.24,6.6 -0.69,3.58 -4.54,6.6 -12.65,9.35 -29.56,14.85Q273.33,366 256,366ZM330.52,323.38 L283.77,242.25q-1.65,-2.75 0.14,-5.5 1.79,-2.75 4.81,-2.75l67.93,0q3.03,0 5.5,2.06 2.48,2.06 3.03,5.09 0.55,3.03 0.69,6.6 0.14,3.58 0.14,8.25 0,17.33 -5.64,34.79Q354.73,308.25 342.9,323.38q-2.2,3.03 -6.33,3.16 -4.13,0.14 -6.05,-3.16z" />
|
||||
</vector>
|
||||
@@ -1,3 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="108dp" android:height="108dp" android:viewportWidth="108" android:viewportHeight="108">
|
||||
<path android:fillColor="#FFFFFFFF" android:pathData="M71.26 37.44c2.02 2.02 3.66 4.4 4.86 7.05l-25.2 0.01 7.88-13.65c1.65 0.27 3.21 0.82 4.76 1.47 2.93 1.19 5.5 2.93 7.7 5.13zm-26.2-5.13c2.93-1.28 6.05-1.83 9.34-1.83 0.82 0 1.56 0 2.38 0.09L44.14 52.28l-7.88-13.65c0.37-0.46 0.73-0.82 1.19-1.28 2.2-2.11 4.76-3.85 7.6-5.04zM32.32 45.05c0.73-1.65 1.56-3.21 2.66-4.67l12.55 21.8H31.77c-0.92-2.47-1.28-5.13-1.28-7.88-0.09-3.21 0.55-6.32 1.83-9.25zm5.13 26.2c-2.02-2.02-3.66-4.4-4.86-7.05h25.38L50 77.84c-1.74-0.27-3.39-0.82-4.94-1.46-2.84-1.28-5.41-3.03-7.61-5.13zm26.2 5.04c-2.93 1.28-6.05 1.83-9.34 1.83-0.73 0-1.47 0-2.2-0.09l8.06-13.93 4.49-7.88 7.79 13.47c-0.46 0.46-0.82 1.01-1.28 1.47-2.11 2.2-4.67 3.94-7.51 5.13zM76.3 63.64c-0.64 1.56-1.47 3.11-2.47 4.49L61.36 46.42h15.57c0.92 2.47 1.28 5.13 1.28 7.88 0 3.21-0.64 6.32-1.92 9.34z"/>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="m261.5,223q-3.03,0 -4.68,-2.75 -1.65,-2.75 0,-5.5l32.17,-55.83q2.2,-3.58 5.5,-4.26 3.3,-0.69 7.15,1.24 18.98,8.53 33.55,23.79 14.58,15.26 22.55,34.51 1.38,3.58 -0.41,6.19 -1.79,2.61 -5.64,2.61zM222.18,236.47 L189.18,179.27q-2.2,-3.58 -1.1,-7.15 1.1,-3.58 4.4,-5.78 13.2,-9.35 29.29,-14.85 16.09,-5.5 34.24,-5.5 4.13,0 9.07,0.41 4.95,0.41 8.25,0.96 3.85,0.55 5.09,3.3 1.24,2.75 -0.69,6.05l-45.92,79.75q-1.65,2.75 -4.81,2.75 -3.16,0 -4.81,-2.75zM155.35,278q-3.03,0 -5.5,-2.06 -2.48,-2.06 -3.03,-5.09 -0.55,-3.03 -0.69,-6.6 -0.14,-3.58 -0.14,-8.25 0,-17.33 5.64,-34.51Q157.27,204.3 169.1,188.9q3.03,-3.85 7.01,-3.85 3.99,0 6.19,4.13l46.2,80.58q1.65,2.75 -0.14,5.5 -1.79,2.75 -4.81,2.75zM210.35,356.1q-18.15,-8.8 -33.28,-23.93 -15.13,-15.13 -22.83,-34.38 -1.38,-3.58 0.55,-6.19 1.93,-2.61 5.78,-2.61l89.65,0q3.03,0 4.68,2.75 1.65,2.75 0,5.5l-31.63,55.28q-2.2,3.58 -5.5,4.68 -3.3,1.1 -7.43,-1.1zM256,366q-3.85,0 -8.66,-0.41Q242.53,365.17 238.95,364.63q-3.85,-0.55 -5.22,-3.3 -1.38,-2.75 0.55,-6.05l45.38,-79.2q1.65,-2.75 5.5,-2.75 3.85,0 5.5,2.75l32.45,56.38q1.93,3.03 1.24,6.6 -0.69,3.58 -4.54,6.6 -12.65,9.35 -29.56,14.85Q273.33,366 256,366ZM330.52,323.38 L283.77,242.25q-1.65,-2.75 0.14,-5.5 1.79,-2.75 4.81,-2.75l67.93,0q3.03,0 5.5,2.06 2.48,2.06 3.03,5.09 0.55,3.03 0.69,6.6 0.14,3.58 0.14,8.25 0,17.33 -5.64,34.79Q354.73,308.25 342.9,323.38q-2.2,3.03 -6.33,3.16 -4.13,0.14 -6.05,-3.16z" />
|
||||
</vector>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_customize_colors_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -76,7 +76,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_purchase_thank_you"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -91,7 +91,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
<org.fossify.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/settings_use_english"
|
||||
style="@style/SettingsCheckboxStyle"
|
||||
android:layout_width="match_parent"
|
||||
@@ -106,14 +106,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_language_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/language" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_language"
|
||||
style="@style/SettingsTextValueStyle"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -147,7 +147,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
<org.fossify.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/settings_sound"
|
||||
style="@style/SettingsCheckboxStyle"
|
||||
android:layout_width="match_parent"
|
||||
@@ -162,7 +162,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
<org.fossify.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/settings_volume_buttons_as_shutter"
|
||||
style="@style/SettingsCheckboxStyle"
|
||||
android:layout_width="match_parent"
|
||||
@@ -195,7 +195,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
<org.fossify.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/settings_save_photo_metadata"
|
||||
style="@style/SettingsCheckboxStyle"
|
||||
android:layout_width="match_parent"
|
||||
@@ -210,7 +210,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
<org.fossify.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/settings_save_photo_video_location"
|
||||
style="@style/SettingsCheckboxStyle"
|
||||
android:layout_width="match_parent"
|
||||
@@ -225,7 +225,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
<org.fossify.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/settings_flip_photos"
|
||||
style="@style/SettingsCheckboxStyle"
|
||||
android:layout_width="match_parent"
|
||||
@@ -240,14 +240,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_save_photos_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/save_photos" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_save_photos"
|
||||
style="@style/SettingsTextValueStyle"
|
||||
android:layout_width="match_parent"
|
||||
@@ -263,14 +263,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_photo_quality_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/photo_compression_quality" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_photo_quality"
|
||||
style="@style/SettingsTextValueStyle"
|
||||
android:layout_width="match_parent"
|
||||
@@ -286,14 +286,14 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_capture_mode_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/capture_mode" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_capture_mode"
|
||||
style="@style/SettingsTextValueStyle"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_orange_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<background android:drawable="@color/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_amber_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_blue_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_blue_grey_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_brown_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_cyan_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_deep_orange_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_deep_purple_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_green_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_grey_black" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_indigo_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_light_blue_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_light_green_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_lime_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_pink_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_purple_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_red_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_teal_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_yellow_700" />
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
||||
</adaptive-icon>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |