Remove paid SDK editor
Why: https://github.com/FossifyOrg/Gallery/discussions/6
This commit is contained in:
parent
b055e3e57b
commit
4e8ff774d4
8 changed files with 2 additions and 708 deletions
|
@ -2,13 +2,10 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import org.jetbrains.kotlin.konan.properties.Properties
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
|
|
||||||
val isProprietary = gradle.startParameter.taskNames.any { task -> task.contains("Proprietary") }
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android)
|
alias(libs.plugins.android)
|
||||||
alias(libs.plugins.kotlinAndroid)
|
alias(libs.plugins.kotlinAndroid)
|
||||||
alias(libs.plugins.ksp)
|
alias(libs.plugins.ksp)
|
||||||
alias(libs.plugins.imgly).apply(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
|
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
|
||||||
|
@ -47,8 +44,7 @@ android {
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
// we cannot change the original package name, else PhotoEditorSDK won't work
|
applicationIdSuffix = ".debug"
|
||||||
//applicationIdSuffix = ".debug"
|
|
||||||
}
|
}
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
|
@ -64,16 +60,12 @@ android {
|
||||||
|
|
||||||
flavorDimensions.add("licensing")
|
flavorDimensions.add("licensing")
|
||||||
productFlavors {
|
productFlavors {
|
||||||
register("proprietary")
|
|
||||||
register("foss")
|
register("foss")
|
||||||
register("prepaid")
|
register("prepaid")
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
getByName("main").java.srcDirs("src/main/kotlin")
|
getByName("main").java.srcDirs("src/main/kotlin")
|
||||||
if (isProprietary) {
|
|
||||||
getByName("main").java.srcDirs("src/proprietary/kotlin")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
@ -93,7 +85,7 @@ android {
|
||||||
abortOnError = false
|
abortOnError = false
|
||||||
}
|
}
|
||||||
|
|
||||||
packagingOptions {
|
packaging {
|
||||||
resources {
|
resources {
|
||||||
excludes += "META-INF/library_release.kotlin_module"
|
excludes += "META-INF/library_release.kotlin_module"
|
||||||
}
|
}
|
||||||
|
@ -129,8 +121,3 @@ dependencies {
|
||||||
implementation(libs.bundles.room)
|
implementation(libs.bundles.room)
|
||||||
ksp(libs.androidx.room.compiler)
|
ksp(libs.androidx.room.compiler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the PESDKPlugin
|
|
||||||
if (isProprietary) {
|
|
||||||
apply(from = "../gradle/imglysdk.gradle")
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:installLocation="auto">
|
|
||||||
|
|
||||||
<application
|
|
||||||
android:name=".App"
|
|
||||||
android:theme="@style/AppTheme">
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".activities.NewPhotoEditActivity"
|
|
||||||
android:exported="true"
|
|
||||||
android:label="@string/advanced_editor">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.EDIT" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
|
|
||||||
<data android:mimeType="image/*" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".activities.NewVideoEditActivity"
|
|
||||||
android:exported="true"
|
|
||||||
android:label="@string/advanced_editor">
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.EDIT" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
|
|
||||||
<data android:mimeType="video/*" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
</manifest>
|
|
|
@ -1,315 +0,0 @@
|
||||||
package org.fossify.gallery.activities
|
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.provider.MediaStore
|
|
||||||
import androidx.exifinterface.media.ExifInterface
|
|
||||||
import org.fossify.commons.extensions.*
|
|
||||||
import org.fossify.commons.helpers.REAL_FILE_PATH
|
|
||||||
import org.fossify.commons.helpers.ensureBackgroundThread
|
|
||||||
import org.fossify.commons.helpers.isNougatPlus
|
|
||||||
import org.fossify.commons.helpers.isRPlus
|
|
||||||
import org.fossify.commons.models.FileDirItem
|
|
||||||
import org.fossify.gallery.R
|
|
||||||
import org.fossify.gallery.dialogs.SaveAsDialog
|
|
||||||
import org.fossify.gallery.extensions.config
|
|
||||||
import org.fossify.gallery.extensions.fixDateTaken
|
|
||||||
import org.fossify.gallery.extensions.tryDeleteFileDirItem
|
|
||||||
import org.fossify.gallery.helpers.getPermissionToRequest
|
|
||||||
import ly.img.android.pesdk.PhotoEditorSettingsList
|
|
||||||
import ly.img.android.pesdk.assets.filter.basic.FilterPackBasic
|
|
||||||
import ly.img.android.pesdk.assets.font.basic.FontPackBasic
|
|
||||||
import ly.img.android.pesdk.assets.overlay.basic.OverlayPackBasic
|
|
||||||
import ly.img.android.pesdk.assets.sticker.animated.StickerPackAnimated
|
|
||||||
import ly.img.android.pesdk.assets.sticker.emoticons.StickerPackEmoticons
|
|
||||||
import ly.img.android.pesdk.assets.sticker.shapes.StickerPackShapes
|
|
||||||
import ly.img.android.pesdk.backend.model.config.CropAspectAsset
|
|
||||||
import ly.img.android.pesdk.backend.model.constant.ImageExportFormat
|
|
||||||
import ly.img.android.pesdk.backend.model.constant.OutputMode
|
|
||||||
import ly.img.android.pesdk.backend.model.state.BrushSettings
|
|
||||||
import ly.img.android.pesdk.backend.model.state.LoadSettings
|
|
||||||
import ly.img.android.pesdk.backend.model.state.PhotoEditorSaveSettings
|
|
||||||
import ly.img.android.pesdk.backend.model.state.manager.SettingsList
|
|
||||||
import ly.img.android.pesdk.ui.activity.PhotoEditorBuilder
|
|
||||||
import ly.img.android.pesdk.ui.model.state.*
|
|
||||||
import ly.img.android.pesdk.ui.panels.item.CropAspectItem
|
|
||||||
import ly.img.android.pesdk.ui.panels.item.PersonalStickerAddItem
|
|
||||||
import ly.img.android.pesdk.ui.panels.item.ToggleAspectItem
|
|
||||||
import java.io.File
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.io.OutputStream
|
|
||||||
|
|
||||||
class NewPhotoEditActivity : SimpleActivity() {
|
|
||||||
private val PESDK_EDIT_IMAGE = 1
|
|
||||||
private val SETTINGS_LIST = "SETTINGS_LIST"
|
|
||||||
private val SOURCE_URI = "SOURCE_URI"
|
|
||||||
private val RESULT_URI = "RESULT_URI"
|
|
||||||
private var sourceFileLastModified = 0L
|
|
||||||
private var oldExif: ExifInterface? = null
|
|
||||||
|
|
||||||
private lateinit var uri: Uri
|
|
||||||
private lateinit var saveUri: Uri
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_new_photo_edit)
|
|
||||||
|
|
||||||
if (checkAppSideloading()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePermission(getPermissionToRequest()) {
|
|
||||||
if (it) {
|
|
||||||
initEditActivity()
|
|
||||||
} else {
|
|
||||||
toast(org.fossify.commons.R.string.no_storage_permissions)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initEditActivity() {
|
|
||||||
if (intent.data == null) {
|
|
||||||
toast(R.string.invalid_image_path)
|
|
||||||
finish()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
uri = intent.data!!
|
|
||||||
if (uri.scheme != "file" && uri.scheme != "content") {
|
|
||||||
toast(R.string.unknown_file_location)
|
|
||||||
finish()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intent.extras?.containsKey(REAL_FILE_PATH) == true) {
|
|
||||||
val realPath = intent.extras!!.getString(REAL_FILE_PATH)
|
|
||||||
uri = when {
|
|
||||||
isPathOnOTG(realPath!!) -> uri
|
|
||||||
realPath.startsWith("file:/") -> Uri.parse(realPath)
|
|
||||||
else -> Uri.fromFile(File(realPath))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(getRealPathFromURI(uri))?.apply {
|
|
||||||
uri = Uri.fromFile(File(this))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
saveUri = when {
|
|
||||||
intent.extras?.containsKey(MediaStore.EXTRA_OUTPUT) == true -> intent.extras!!.get(MediaStore.EXTRA_OUTPUT) as Uri
|
|
||||||
else -> uri
|
|
||||||
}
|
|
||||||
|
|
||||||
openEditor(uri)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
|
||||||
if (requestCode == PESDK_EDIT_IMAGE) {
|
|
||||||
val extras = resultData?.extras
|
|
||||||
val resultPath = extras?.get(RESULT_URI)?.toString() ?: ""
|
|
||||||
val sourcePath = Uri.decode(extras?.get(SOURCE_URI)?.toString() ?: "")
|
|
||||||
val settings = extras?.getParcelable<SettingsList>(SETTINGS_LIST)
|
|
||||||
if (settings != null) {
|
|
||||||
val brush = settings.getSettingsModel(BrushSettings::class.java)
|
|
||||||
config.editorBrushColor = brush.brushColor
|
|
||||||
config.editorBrushHardness = brush.brushHardness
|
|
||||||
config.editorBrushSize = brush.brushSize
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultCode != Activity.RESULT_OK || resultPath.isEmpty()) {
|
|
||||||
toast(R.string.image_editing_cancelled)
|
|
||||||
finish()
|
|
||||||
} else {
|
|
||||||
val source = if (sourcePath.isEmpty() || sourcePath.startsWith("content")) {
|
|
||||||
internalStoragePath
|
|
||||||
} else {
|
|
||||||
sourcePath.substringAfter("file://")
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveAsDialog(this, source, true, cancelCallback = {
|
|
||||||
toast(R.string.image_editing_failed)
|
|
||||||
finish()
|
|
||||||
}, callback = {
|
|
||||||
val destinationFilePath = it
|
|
||||||
handleSAFDialog(destinationFilePath) {
|
|
||||||
if (it) {
|
|
||||||
ensureBackgroundThread {
|
|
||||||
storeOldExif(source)
|
|
||||||
sourceFileLastModified = File(source).lastModified()
|
|
||||||
|
|
||||||
handleFileOverwriting(destinationFilePath) {
|
|
||||||
var inputStream: InputStream? = null
|
|
||||||
var outputStream: OutputStream? = null
|
|
||||||
try {
|
|
||||||
inputStream = contentResolver.openInputStream(Uri.parse(resultPath))
|
|
||||||
outputStream = getFileOutputStreamSync(destinationFilePath, destinationFilePath.getMimeType())
|
|
||||||
inputStream!!.copyTo(outputStream!!)
|
|
||||||
outputStream.flush()
|
|
||||||
inputStream.close()
|
|
||||||
outputStream.close()
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (isNougatPlus()) {
|
|
||||||
val newExif = ExifInterface(destinationFilePath)
|
|
||||||
oldExif?.copyTo(newExif, false)
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.keepLastModified) {
|
|
||||||
// add 1 s to the last modified time to properly update the thumbnail
|
|
||||||
updateLastModified(destinationFilePath, sourceFileLastModified + 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
val paths = arrayListOf(destinationFilePath)
|
|
||||||
rescanPaths(arrayListOf(destinationFilePath)) {
|
|
||||||
fixDateTaken(paths, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
setResult(Activity.RESULT_OK, intent)
|
|
||||||
toast(R.string.file_edited_successfully)
|
|
||||||
finish()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showErrorToast(e)
|
|
||||||
} finally {
|
|
||||||
inputStream?.close()
|
|
||||||
outputStream?.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toast(R.string.image_editing_failed)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.onActivityResult(requestCode, resultCode, resultData)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
|
||||||
private fun storeOldExif(sourcePath: String) {
|
|
||||||
var inputStream: InputStream? = null
|
|
||||||
try {
|
|
||||||
if (isNougatPlus()) {
|
|
||||||
inputStream = contentResolver.openInputStream(Uri.fromFile(File(sourcePath)))
|
|
||||||
oldExif = ExifInterface(inputStream!!)
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
} finally {
|
|
||||||
inputStream?.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case the user wants to overwrite the original file and it is on an SD card, delete it manually first. Else the system just appends (1)
|
|
||||||
private fun handleFileOverwriting(path: String, callback: () -> Unit) {
|
|
||||||
if ((!isRPlus() || isExternalStorageManager()) && getDoesFilePathExist(path) && isPathOnSD(path)) {
|
|
||||||
val fileDirItem = FileDirItem(path, path.getFilenameFromPath())
|
|
||||||
tryDeleteFileDirItem(fileDirItem, false, true) { success ->
|
|
||||||
if (success) {
|
|
||||||
callback()
|
|
||||||
} else {
|
|
||||||
toast(org.fossify.commons.R.string.unknown_error_occurred)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openEditor(inputImage: Uri) {
|
|
||||||
val settingsList = createPesdkSettingsList()
|
|
||||||
|
|
||||||
settingsList.configure<LoadSettings> {
|
|
||||||
it.source = inputImage
|
|
||||||
}
|
|
||||||
|
|
||||||
settingsList[LoadSettings::class].source = inputImage
|
|
||||||
|
|
||||||
PhotoEditorBuilder(this)
|
|
||||||
.setSettingsList(settingsList)
|
|
||||||
.startActivityForResult(this, PESDK_EDIT_IMAGE)
|
|
||||||
|
|
||||||
settingsList.release()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createPesdkSettingsList(): PhotoEditorSettingsList {
|
|
||||||
val settingsList = PhotoEditorSettingsList(false).apply {
|
|
||||||
configure<UiConfigFilter> {
|
|
||||||
it.setFilterList(FilterPackBasic.getFilterPack())
|
|
||||||
}
|
|
||||||
|
|
||||||
configure<UiConfigText> {
|
|
||||||
it.setFontList(FontPackBasic.getFontPack())
|
|
||||||
}
|
|
||||||
|
|
||||||
config.getAssetMap(CropAspectAsset::class.java).apply {
|
|
||||||
add(CropAspectAsset("my_crop_1_2", 1, 2, false))
|
|
||||||
add(CropAspectAsset("my_crop_2_1", 2, 1, false))
|
|
||||||
add(CropAspectAsset("my_crop_19_9", 19, 9, false))
|
|
||||||
add(CropAspectAsset("my_crop_9_19", 9, 19, false))
|
|
||||||
add(CropAspectAsset("my_crop_20_9", 20, 9, false))
|
|
||||||
add(CropAspectAsset("my_crop_9_20", 9, 20, false))
|
|
||||||
add(CropAspectAsset("my_crop_21_9", 21, 9, false))
|
|
||||||
add(CropAspectAsset("my_crop_9_21", 9, 21, false))
|
|
||||||
add(CropAspectAsset("my_crop_5_4", 5, 4, false))
|
|
||||||
add(CropAspectAsset("my_crop_4_5", 4, 5, false))
|
|
||||||
add(CropAspectAsset("my_crop_37_18", 37, 18, false))
|
|
||||||
add(CropAspectAsset("my_crop_18_37", 18, 37, false))
|
|
||||||
add(CropAspectAsset("my_crop_16_10", 16, 10, false))
|
|
||||||
add(CropAspectAsset("my_crop_10_16", 10, 16, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
getSettingsModel(UiConfigAspect::class.java).aspectList.apply {
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_2_1"), CropAspectItem("my_crop_1_2")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_19_9"), CropAspectItem("my_crop_9_19")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_20_9"), CropAspectItem("my_crop_9_20")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_21_9"), CropAspectItem("my_crop_9_21")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_5_4"), CropAspectItem("my_crop_4_5")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_37_18"), CropAspectItem("my_crop_18_37")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_16_10"), CropAspectItem("my_crop_10_16")))
|
|
||||||
}
|
|
||||||
|
|
||||||
getSettingsModel(BrushSettings::class.java).apply {
|
|
||||||
brushColor = applicationContext.config.editorBrushColor
|
|
||||||
brushHardness = applicationContext.config.editorBrushHardness
|
|
||||||
brushSize = applicationContext.config.editorBrushSize
|
|
||||||
}
|
|
||||||
|
|
||||||
configure<UiConfigOverlay> {
|
|
||||||
it.setOverlayList(OverlayPackBasic.getOverlayPack())
|
|
||||||
}
|
|
||||||
|
|
||||||
configure<UiConfigSticker> {
|
|
||||||
it.setStickerLists(
|
|
||||||
PersonalStickerAddItem(),
|
|
||||||
StickerPackEmoticons.getStickerCategory(),
|
|
||||||
StickerPackShapes.getStickerCategory(),
|
|
||||||
StickerPackAnimated.getStickerCategory()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val theme = if (isUsingSystemDarkTheme()) {
|
|
||||||
ly.img.android.pesdk.ui.R.style.Theme_Imgly_NoFullscreen
|
|
||||||
} else {
|
|
||||||
ly.img.android.pesdk.ui.R.style.Theme_Imgly_Light_NoFullscreen
|
|
||||||
}
|
|
||||||
|
|
||||||
getSettingsModel(UiConfigTheme::class.java).theme = theme
|
|
||||||
|
|
||||||
configure<PhotoEditorSaveSettings> {
|
|
||||||
it.setExportFormat(ImageExportFormat.AUTO)
|
|
||||||
it.setOutputToTemp()
|
|
||||||
it.outputMode = OutputMode.EXPORT_IF_NECESSARY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return settingsList
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,293 +0,0 @@
|
||||||
package org.fossify.gallery.activities
|
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.provider.MediaStore
|
|
||||||
import androidx.exifinterface.media.ExifInterface
|
|
||||||
import org.fossify.commons.extensions.*
|
|
||||||
import org.fossify.commons.helpers.*
|
|
||||||
import org.fossify.commons.models.FileDirItem
|
|
||||||
import org.fossify.gallery.R
|
|
||||||
import org.fossify.gallery.dialogs.SaveAsDialog
|
|
||||||
import org.fossify.gallery.extensions.config
|
|
||||||
import org.fossify.gallery.extensions.fixDateTaken
|
|
||||||
import org.fossify.gallery.extensions.tryDeleteFileDirItem
|
|
||||||
import org.fossify.gallery.helpers.getPermissionToRequest
|
|
||||||
import ly.img.android.pesdk.VideoEditorSettingsList
|
|
||||||
import ly.img.android.pesdk.assets.filter.basic.FilterPackBasic
|
|
||||||
import ly.img.android.pesdk.assets.font.basic.FontPackBasic
|
|
||||||
import ly.img.android.pesdk.assets.overlay.basic.OverlayPackBasic
|
|
||||||
import ly.img.android.pesdk.assets.sticker.animated.StickerPackAnimated
|
|
||||||
import ly.img.android.pesdk.assets.sticker.emoticons.StickerPackEmoticons
|
|
||||||
import ly.img.android.pesdk.assets.sticker.shapes.StickerPackShapes
|
|
||||||
import ly.img.android.pesdk.backend.model.config.CropAspectAsset
|
|
||||||
import ly.img.android.pesdk.backend.model.constant.OutputMode
|
|
||||||
import ly.img.android.pesdk.backend.model.state.BrushSettings
|
|
||||||
import ly.img.android.pesdk.backend.model.state.LoadSettings
|
|
||||||
import ly.img.android.pesdk.backend.model.state.VideoEditorSaveSettings
|
|
||||||
import ly.img.android.pesdk.backend.model.state.manager.SettingsList
|
|
||||||
import ly.img.android.pesdk.ui.activity.VideoEditorBuilder
|
|
||||||
import ly.img.android.pesdk.ui.model.state.*
|
|
||||||
import ly.img.android.pesdk.ui.panels.item.CropAspectItem
|
|
||||||
import ly.img.android.pesdk.ui.panels.item.PersonalStickerAddItem
|
|
||||||
import ly.img.android.pesdk.ui.panels.item.ToggleAspectItem
|
|
||||||
import java.io.File
|
|
||||||
import java.io.InputStream
|
|
||||||
|
|
||||||
class NewVideoEditActivity : SimpleActivity() {
|
|
||||||
private val VESDK_EDIT_VIDEO = 1
|
|
||||||
private val SETTINGS_LIST = "SETTINGS_LIST"
|
|
||||||
private val SOURCE_URI = "SOURCE_URI"
|
|
||||||
private val RESULT_URI = "RESULT_URI"
|
|
||||||
private var sourceFileLastModified = 0L
|
|
||||||
private var oldExif: ExifInterface? = null
|
|
||||||
|
|
||||||
private lateinit var uri: Uri
|
|
||||||
private lateinit var saveUri: Uri
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_new_video_edit)
|
|
||||||
|
|
||||||
if (checkAppSideloading()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePermission(getPermissionToRequest()) {
|
|
||||||
if (it) {
|
|
||||||
initEditActivity()
|
|
||||||
} else {
|
|
||||||
toast(org.fossify.commons.R.string.no_storage_permissions)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initEditActivity() {
|
|
||||||
if (intent.data == null) {
|
|
||||||
toast(R.string.invalid_video_path)
|
|
||||||
finish()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
uri = intent.data!!
|
|
||||||
if (uri.scheme != "file" && uri.scheme != "content") {
|
|
||||||
toast(R.string.unknown_file_location)
|
|
||||||
finish()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intent.extras?.containsKey(REAL_FILE_PATH) == true) {
|
|
||||||
val realPath = intent.extras!!.getString(REAL_FILE_PATH)
|
|
||||||
uri = when {
|
|
||||||
isPathOnOTG(realPath!!) -> uri
|
|
||||||
realPath.startsWith("file:/") -> Uri.parse(realPath)
|
|
||||||
else -> Uri.fromFile(File(realPath))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(getRealPathFromURI(uri))?.apply {
|
|
||||||
uri = Uri.fromFile(File(this))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
saveUri = when {
|
|
||||||
intent.extras?.containsKey(MediaStore.EXTRA_OUTPUT) == true -> intent.extras!!.get(MediaStore.EXTRA_OUTPUT) as Uri
|
|
||||||
else -> uri
|
|
||||||
}
|
|
||||||
|
|
||||||
openEditor(uri)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
|
|
||||||
if (requestCode == VESDK_EDIT_VIDEO) {
|
|
||||||
val extras = resultData?.extras
|
|
||||||
val resultPath = extras?.get(RESULT_URI)?.toString() ?: ""
|
|
||||||
val sourcePath = Uri.decode(extras?.get(SOURCE_URI)?.toString() ?: "")
|
|
||||||
|
|
||||||
val settings = extras?.getParcelable<SettingsList>(SETTINGS_LIST)
|
|
||||||
if (settings != null) {
|
|
||||||
val brush = settings.getSettingsModel(BrushSettings::class.java)
|
|
||||||
config.editorBrushColor = brush.brushColor
|
|
||||||
config.editorBrushHardness = brush.brushHardness
|
|
||||||
config.editorBrushSize = brush.brushSize
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultCode != Activity.RESULT_OK || resultPath.isEmpty()) {
|
|
||||||
toast(R.string.video_editing_cancelled)
|
|
||||||
finish()
|
|
||||||
} else {
|
|
||||||
val source = if (sourcePath.isEmpty() || sourcePath.startsWith("content")) {
|
|
||||||
internalStoragePath
|
|
||||||
} else {
|
|
||||||
sourcePath.substringAfter("file://")
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveAsDialog(this, source, true, cancelCallback = {
|
|
||||||
toast(R.string.video_editing_failed)
|
|
||||||
finish()
|
|
||||||
}, callback = {
|
|
||||||
val destinationFilePath = it
|
|
||||||
handleSAFDialog(destinationFilePath) {
|
|
||||||
if (it) {
|
|
||||||
ensureBackgroundThread {
|
|
||||||
storeOldExif(source)
|
|
||||||
sourceFileLastModified = File(source).lastModified()
|
|
||||||
|
|
||||||
handleFileOverwriting(destinationFilePath) {
|
|
||||||
try {
|
|
||||||
val inputStream = contentResolver.openInputStream(Uri.parse(resultPath))
|
|
||||||
val outputStream = getFileOutputStreamSync(destinationFilePath, destinationFilePath.getMimeType())
|
|
||||||
inputStream?.use {
|
|
||||||
outputStream?.use {
|
|
||||||
inputStream.copyTo(outputStream)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.keepLastModified) {
|
|
||||||
// add 1 s to the last modified time to properly update the thumbnail
|
|
||||||
updateLastModified(destinationFilePath, sourceFileLastModified + 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
val paths = arrayListOf(destinationFilePath)
|
|
||||||
rescanPaths(paths) {
|
|
||||||
fixDateTaken(paths, false)
|
|
||||||
|
|
||||||
setResult(Activity.RESULT_OK)
|
|
||||||
toast(R.string.file_edited_successfully)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
showErrorToast(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toast(R.string.video_editing_failed)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.onActivityResult(requestCode, resultCode, resultData)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
|
||||||
private fun storeOldExif(sourcePath: String) {
|
|
||||||
var inputStream: InputStream? = null
|
|
||||||
try {
|
|
||||||
if (isNougatPlus()) {
|
|
||||||
inputStream = contentResolver.openInputStream(Uri.fromFile(File(sourcePath)))
|
|
||||||
oldExif = ExifInterface(inputStream!!)
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
} finally {
|
|
||||||
inputStream?.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case the user wants to overwrite the original file and it is on an SD card, delete it manually first. Else the system just appends (1)
|
|
||||||
private fun handleFileOverwriting(path: String, callback: () -> Unit) {
|
|
||||||
if (!isRPlus() && getDoesFilePathExist(path) && isPathOnSD(path)) {
|
|
||||||
val fileDirItem = FileDirItem(path, path.getFilenameFromPath())
|
|
||||||
tryDeleteFileDirItem(fileDirItem, false, true) { success ->
|
|
||||||
if (success) {
|
|
||||||
callback()
|
|
||||||
} else {
|
|
||||||
toast(org.fossify.commons.R.string.unknown_error_occurred)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openEditor(inputVideo: Uri) {
|
|
||||||
val settingsList = createVesdkSettingsList()
|
|
||||||
|
|
||||||
settingsList.configure<LoadSettings> {
|
|
||||||
it.source = inputVideo
|
|
||||||
}
|
|
||||||
|
|
||||||
settingsList[LoadSettings::class].source = inputVideo
|
|
||||||
|
|
||||||
VideoEditorBuilder(this)
|
|
||||||
.setSettingsList(settingsList)
|
|
||||||
.startActivityForResult(this, VESDK_EDIT_VIDEO)
|
|
||||||
|
|
||||||
settingsList.release()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createVesdkSettingsList(): VideoEditorSettingsList {
|
|
||||||
val settingsList = VideoEditorSettingsList(false).apply {
|
|
||||||
configure<UiConfigFilter> {
|
|
||||||
it.setFilterList(FilterPackBasic.getFilterPack())
|
|
||||||
}
|
|
||||||
|
|
||||||
configure<UiConfigText> {
|
|
||||||
it.setFontList(FontPackBasic.getFontPack())
|
|
||||||
}
|
|
||||||
|
|
||||||
config.getAssetMap(CropAspectAsset::class.java).apply {
|
|
||||||
add(CropAspectAsset("my_crop_1_2", 1, 2, false))
|
|
||||||
add(CropAspectAsset("my_crop_2_1", 2, 1, false))
|
|
||||||
add(CropAspectAsset("my_crop_19_9", 19, 9, false))
|
|
||||||
add(CropAspectAsset("my_crop_9_19", 9, 19, false))
|
|
||||||
add(CropAspectAsset("my_crop_5_4", 5, 4, false))
|
|
||||||
add(CropAspectAsset("my_crop_4_5", 4, 5, false))
|
|
||||||
add(CropAspectAsset("my_crop_37_18", 37, 18, false))
|
|
||||||
add(CropAspectAsset("my_crop_18_37", 18, 37, false))
|
|
||||||
add(CropAspectAsset("my_crop_16_10", 16, 10, false))
|
|
||||||
add(CropAspectAsset("my_crop_10_16", 10, 16, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
getSettingsModel(UiConfigAspect::class.java).aspectList.apply {
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_2_1"), CropAspectItem("my_crop_1_2")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_19_9"), CropAspectItem("my_crop_9_19")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_5_4"), CropAspectItem("my_crop_4_5")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_37_18"), CropAspectItem("my_crop_18_37")))
|
|
||||||
add(ToggleAspectItem(CropAspectItem("my_crop_16_10"), CropAspectItem("my_crop_10_16")))
|
|
||||||
}
|
|
||||||
|
|
||||||
getSettingsModel(BrushSettings::class.java).apply {
|
|
||||||
brushColor = applicationContext.config.editorBrushColor
|
|
||||||
brushHardness = applicationContext.config.editorBrushHardness
|
|
||||||
brushSize = applicationContext.config.editorBrushSize
|
|
||||||
}
|
|
||||||
|
|
||||||
configure<UiConfigOverlay> {
|
|
||||||
it.setOverlayList(OverlayPackBasic.getOverlayPack())
|
|
||||||
}
|
|
||||||
|
|
||||||
configure<UiConfigSticker> {
|
|
||||||
it.setStickerLists(
|
|
||||||
PersonalStickerAddItem(),
|
|
||||||
StickerPackEmoticons.getStickerCategory(),
|
|
||||||
StickerPackShapes.getStickerCategory(),
|
|
||||||
StickerPackAnimated.getStickerCategory()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val theme = if (isUsingSystemDarkTheme()) {
|
|
||||||
ly.img.android.pesdk.ui.R.style.Theme_Imgly_NoFullscreen
|
|
||||||
} else {
|
|
||||||
ly.img.android.pesdk.ui.R.style.Theme_Imgly_Light_NoFullscreen
|
|
||||||
}
|
|
||||||
|
|
||||||
getSettingsModel(UiConfigTheme::class.java).theme = theme
|
|
||||||
|
|
||||||
configure<VideoEditorSaveSettings> {
|
|
||||||
it.allowOrientationMatrixMetadata = true
|
|
||||||
it.setOutputToTemp()
|
|
||||||
it.outputMode = OutputMode.EXPORT_IF_NECESSARY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return settingsList
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,5 +2,4 @@ plugins {
|
||||||
alias(libs.plugins.android).apply(false)
|
alias(libs.plugins.android).apply(false)
|
||||||
alias(libs.plugins.kotlinAndroid).apply(false)
|
alias(libs.plugins.kotlinAndroid).apply(false)
|
||||||
alias(libs.plugins.ksp).apply(false)
|
alias(libs.plugins.ksp).apply(false)
|
||||||
alias(libs.plugins.imgly).apply(false)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
// This file had to stay in Groovy
|
|
||||||
// Since just converting it to Kotlin will not work
|
|
||||||
// There needs to be a way to conditinally apply this plugin
|
|
||||||
// But that results in missing references for `imglyConfig`
|
|
||||||
apply plugin: 'ly.img.android.sdk'
|
|
||||||
|
|
||||||
imglyConfig {
|
|
||||||
vesdk {
|
|
||||||
enabled true
|
|
||||||
licensePath 'vesdk_android_license'
|
|
||||||
}
|
|
||||||
|
|
||||||
pesdk {
|
|
||||||
enabled true
|
|
||||||
licensePath 'pesdk_android_license'
|
|
||||||
}
|
|
||||||
|
|
||||||
modules {
|
|
||||||
include 'ui:video-trim'
|
|
||||||
include 'ui:core'
|
|
||||||
include 'ui:text'
|
|
||||||
include 'ui:focus'
|
|
||||||
include 'ui:brush'
|
|
||||||
include 'ui:filter'
|
|
||||||
include 'ui:sticker'
|
|
||||||
include 'ui:overlay'
|
|
||||||
include 'ui:transform'
|
|
||||||
include 'ui:adjustment'
|
|
||||||
include 'ui:video-composition'
|
|
||||||
|
|
||||||
include 'backend:serializer'
|
|
||||||
include 'backend:sticker-smart'
|
|
||||||
include 'backend:sticker-animated'
|
|
||||||
|
|
||||||
include 'assets:font-basic'
|
|
||||||
include 'assets:filter-basic'
|
|
||||||
include 'assets:overlay-basic'
|
|
||||||
include 'assets:sticker-shapes'
|
|
||||||
include 'assets:sticker-emoticons'
|
|
||||||
include 'assets:sticker-animated'
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,4 @@
|
||||||
[versions]
|
[versions]
|
||||||
#imgly
|
|
||||||
imgly = "10.7.3"
|
|
||||||
#jetbrains
|
#jetbrains
|
||||||
kotlin = "1.8.22"
|
kotlin = "1.8.22"
|
||||||
#KSP
|
#KSP
|
||||||
|
@ -83,4 +81,3 @@ room = [
|
||||||
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
|
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
|
||||||
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||||
imgly = { id = "ly.img.android.sdk", version.ref = "imgly" }
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ pluginManagement {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven(url = "https://artifactory.img.ly/artifactory/imgly")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
|
@ -14,7 +13,6 @@ dependencyResolutionManagement {
|
||||||
jcenter()
|
jcenter()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { setUrl("https://jitpack.io") }
|
maven { setUrl("https://jitpack.io") }
|
||||||
maven(url = "https://artifactory.img.ly/artifactory/imgly")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue