Video speedup/slowdown
This commit is contained in:
parent
ec1b77df74
commit
fec3f91386
|
@ -1,7 +1,7 @@
|
|||
import com.android.build.api.dsl.ManagedVirtualDevice
|
||||
|
||||
plugins {
|
||||
id "com.cookpad.android.plugin.license-tools" version "1.2.2"
|
||||
id "com.cookpad.android.plugin.license-tools" version "1.2.8"
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
|
|
@ -47,7 +47,7 @@ import java.io.OutputStream
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
import kotlin.collections.flatten
|
||||
|
||||
const val TAG = "Post Creation Activity"
|
||||
|
||||
|
@ -130,8 +130,10 @@ class PostCreationActivity : BaseThemedWithoutBarActivity() {
|
|||
uiState.newEncodingJobMuted?.let { muted ->
|
||||
uiState.newEncodingJobVideoStart?.let { videoStart ->
|
||||
uiState.newEncodingJobVideoEnd?.let { videoEnd ->
|
||||
startEncoding(position, muted, videoStart, videoEnd)
|
||||
model.encodingStarted()
|
||||
uiState.newEncodingJobSpeedIndex?.let { speedIndex ->
|
||||
startEncoding(position, muted, videoStart, videoEnd, speedIndex)
|
||||
model.encodingStarted()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -324,7 +326,13 @@ class PostCreationActivity : BaseThemedWithoutBarActivity() {
|
|||
* @param videoEnd when we want to end the video, in seconds, or null if we
|
||||
* don't want to remove the end
|
||||
*/
|
||||
private fun startEncoding(position: Int, muted: Boolean, videoStart: Float?, videoEnd: Float?) {
|
||||
private fun startEncoding(
|
||||
position: Int,
|
||||
muted: Boolean,
|
||||
videoStart: Float?,
|
||||
videoEnd: Float?,
|
||||
speedIndex: Int
|
||||
) {
|
||||
val originalUri = model.getPhotoData().value!![position].imageUri
|
||||
|
||||
// Having a meaningful suffix is necessary so that ffmpeg knows what to put in output
|
||||
|
@ -342,13 +350,32 @@ class PostCreationActivity : BaseThemedWithoutBarActivity() {
|
|||
val mediaInformation: MediaInformation? = FFprobeKit.getMediaInformation(ffmpegCompliantUri(inputUri)).mediaInformation
|
||||
val totalVideoDuration = mediaInformation?.duration?.toFloatOrNull()
|
||||
|
||||
val mutedString = if(muted) "-an" else null
|
||||
val startString: List<String?> = if(videoStart != null) listOf("-ss", "$videoStart") else listOf(null, null)
|
||||
val speed = VideoEditActivity.speedChoices[speedIndex]
|
||||
|
||||
val endString: List<String?> = if(videoEnd != null) listOf("-to", "${videoEnd - (videoStart ?: 0f)}") else listOf(null, null)
|
||||
//TODO also have audio when speed is changed?
|
||||
val mutedString = if(muted || speedIndex != 1) "-an" else null
|
||||
val startString: List<String?> = if(videoStart != null) listOf("-ss", "${videoStart/speed.toFloat()}") else listOf(null, null)
|
||||
|
||||
val endString: List<String?> = if(videoEnd != null) listOf("-to", "${videoEnd/speed.toFloat() - (videoStart ?: 0f)/speed.toFloat()}") else listOf(null, null)
|
||||
|
||||
val speedString: List<String?> = if(speedIndex!= 1)
|
||||
listOf("-filter:v", "setpts=PTS/${speed}")
|
||||
// Stream copy is not compatible with filter, but when not filtering we can copy the stream without re-encoding
|
||||
else listOf("-c", "copy")
|
||||
|
||||
// This should be set when re-encoding is required (otherwise it defaults to mpeg which then doesn't play)
|
||||
val encodePreset: List<String?> = if(speedIndex != 1) listOf("-c:v", "libx264", "-preset", "ultrafast") else listOf(null, null, null, null)
|
||||
|
||||
val session: FFmpegSession =
|
||||
FFmpegKit.executeWithArgumentsAsync(listOfNotNull(startString[0], startString[1], "-i", ffmpegCompliantUri, endString[0], endString[1], "-c", "copy", mutedString, "-y", outputVideoPath).toTypedArray(),
|
||||
FFmpegKit.executeWithArgumentsAsync(listOfNotNull(
|
||||
startString[0], startString[1],
|
||||
"-i", ffmpegCompliantUri,
|
||||
speedString[0], speedString[1],
|
||||
endString[0], endString[1],
|
||||
mutedString, "-y",
|
||||
encodePreset[0], encodePreset[1], encodePreset[2], encodePreset[3],
|
||||
outputVideoPath
|
||||
).toTypedArray(),
|
||||
//val session: FFmpegSession = FFmpegKit.executeAsync("$startString -i $inputSafePath $endString -c:v libvpx-vp9 -c:a copy -an -y $outputVideoPath",
|
||||
{ session ->
|
||||
val returnCode = session.returnCode
|
||||
|
@ -387,7 +414,9 @@ class PostCreationActivity : BaseThemedWithoutBarActivity() {
|
|||
timeInMilliseconds?.let {
|
||||
if (timeInMilliseconds > 0) {
|
||||
val completePercentage = totalVideoDuration?.let {
|
||||
val newTotalDuration = it - (videoStart ?: 0f) - (it - (videoEnd ?: it))
|
||||
val speedupDurationModifier = VideoEditActivity.speedChoices[speedIndex].toFloat()
|
||||
|
||||
val newTotalDuration = (it - (videoStart ?: 0f) - (it - (videoEnd ?: it)))/speedupDurationModifier
|
||||
timeInMilliseconds / (10*newTotalDuration)
|
||||
}
|
||||
resultHandler.post {
|
||||
|
|
|
@ -58,6 +58,7 @@ data class PostCreationActivityUiState(
|
|||
|
||||
val newEncodingJobPosition: Int? = null,
|
||||
val newEncodingJobMuted: Boolean? = null,
|
||||
val newEncodingJobSpeedIndex: Int? = null,
|
||||
val newEncodingJobVideoStart: Float? = null,
|
||||
val newEncodingJobVideoEnd: Float? = null,
|
||||
)
|
||||
|
@ -96,6 +97,7 @@ class PostCreationViewModel(application: Application, clipdata: ClipData? = null
|
|||
currentUiState.copy(
|
||||
newEncodingJobPosition = null,
|
||||
newEncodingJobMuted = null,
|
||||
newEncodingJobSpeedIndex = null,
|
||||
newEncodingJobVideoStart = null,
|
||||
newEncodingJobVideoEnd = null,
|
||||
)
|
||||
|
@ -332,7 +334,7 @@ class PostCreationViewModel(application: Application, clipdata: ClipData? = null
|
|||
Toast.LENGTH_SHORT).show()
|
||||
val intent = Intent(getApplication(), MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
//TODO make the activity launch this instead (and surrounding toasts too)L
|
||||
//TODO make the activity launch this instead (and surrounding toasts too)
|
||||
getApplication<PixelDroidApplication>().startActivity(intent)
|
||||
} catch (exception: IOException) {
|
||||
Toast.makeText(getApplication(), getApplication<PixelDroidApplication>().getString(R.string.upload_post_error),
|
||||
|
@ -359,21 +361,24 @@ class PostCreationViewModel(application: Application, clipdata: ClipData? = null
|
|||
fun modifyAt(position: Int, data: Intent): Unit? {
|
||||
val result: PhotoData = photoData.value?.getOrNull(position)?.run {
|
||||
if (video) {
|
||||
val muted: Boolean = data.getBooleanExtra(VideoEditActivity.MUTED, false)
|
||||
val videoStart: Float? = data.getFloatExtra(VideoEditActivity.VIDEO_START, -1f).let {
|
||||
if(it == -1f) null else it
|
||||
}
|
||||
val modified: Boolean = data.getBooleanExtra(VideoEditActivity.MODIFIED, false)
|
||||
val videoEnd: Float? = data.getFloatExtra(VideoEditActivity.VIDEO_END, -1f).let {
|
||||
if(it == -1f) null else it
|
||||
}
|
||||
if(modified){
|
||||
val muted: Boolean = data.getBooleanExtra(VideoEditActivity.MUTED, false)
|
||||
val speedIndex: Int = data.getIntExtra(VideoEditActivity.SPEED, 1)
|
||||
val videoStart: Float? = data.getFloatExtra(VideoEditActivity.VIDEO_START, -1f).let {
|
||||
if(it == -1f) null else it
|
||||
}
|
||||
val videoEnd: Float? = data.getFloatExtra(VideoEditActivity.VIDEO_END, -1f).let {
|
||||
if(it == -1f) null else it
|
||||
}
|
||||
|
||||
videoEncodeProgress = 0
|
||||
sessionMap[position]?.let { FFmpegKit.cancel(it) }
|
||||
_uiState.update { currentUiState ->
|
||||
currentUiState.copy(
|
||||
newEncodingJobPosition = position,
|
||||
newEncodingJobMuted = muted,
|
||||
newEncodingJobSpeedIndex = speedIndex,
|
||||
newEncodingJobVideoStart = videoStart,
|
||||
newEncodingJobVideoEnd = videoEnd
|
||||
)
|
||||
|
|
|
@ -93,16 +93,15 @@ class ImageCarousel(
|
|||
if (position != RecyclerView.NO_POSITION && field != position) {
|
||||
val thisProgress = data?.getOrNull(position)?.encodeProgress
|
||||
if (thisProgress != null) {
|
||||
binding.encodeInfoCard.visibility = VISIBLE
|
||||
binding.encodeProgress.visibility = VISIBLE
|
||||
binding.encodeInfoText.visibility = VISIBLE
|
||||
binding.encodeInfoText.text =
|
||||
context.getString(R.string.encode_progress).format(thisProgress)
|
||||
binding.encodeProgress.progress = thisProgress
|
||||
} else {
|
||||
binding.encodeProgress.visibility = INVISIBLE
|
||||
binding.encodeInfoText.visibility = INVISIBLE
|
||||
binding.encodeInfoCard.visibility = GONE
|
||||
}
|
||||
} else binding.encodeProgress.visibility = INVISIBLE
|
||||
} else if(position == RecyclerView.NO_POSITION) binding.encodeInfoCard.visibility = GONE
|
||||
|
||||
if (position != RecyclerView.NO_POSITION && recyclerView.scrollState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
recyclerView.smoothScrollToPosition(position)
|
||||
|
@ -567,8 +566,7 @@ class ImageCarousel(
|
|||
data?.getOrNull(position)?.encodeProgress = progress
|
||||
if(currentPosition == position) {
|
||||
if (progress == null) {
|
||||
binding.encodeProgress.visibility = INVISIBLE
|
||||
binding.encodeInfoText.visibility = VISIBLE
|
||||
binding.encodeProgress.visibility = GONE
|
||||
if(error){
|
||||
binding.encodeInfoText.setText(R.string.encode_error)
|
||||
binding.encodeInfoText.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(context, R.drawable.error),
|
||||
|
@ -581,8 +579,8 @@ class ImageCarousel(
|
|||
}
|
||||
} else {
|
||||
binding.encodeProgress.visibility = VISIBLE
|
||||
binding.encodeInfoCard.visibility = VISIBLE
|
||||
binding.encodeProgress.progress = progress
|
||||
binding.encodeInfoText.visibility = VISIBLE
|
||||
binding.encodeInfoText.text = context.getString(R.string.encode_progress).format(progress)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.app.AlertDialog
|
|||
import android.content.Intent
|
||||
import android.media.AudioManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
|
@ -21,6 +22,7 @@ import androidx.media.AudioAttributesCompat
|
|||
import androidx.media2.common.MediaMetadata
|
||||
import androidx.media2.common.UriMediaItem
|
||||
import androidx.media2.player.MediaPlayer
|
||||
import androidx.media2.player.MediaPlayer.PlayerCallback
|
||||
import com.arthenica.ffmpegkit.*
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.slider.RangeSlider
|
||||
|
@ -37,6 +39,17 @@ class VideoEditActivity : BaseThemedWithBarActivity() {
|
|||
|
||||
private lateinit var mediaPlayer: MediaPlayer
|
||||
private var videoPosition: Int = -1
|
||||
|
||||
//TODO react to change of playbackSpeed (when changed in the player itself)
|
||||
private var speed: Int = 1
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
mediaPlayer.playbackSpeed = speedChoices[value].toFloat()
|
||||
|
||||
if(speed != 1) binding.muter.callOnClick()
|
||||
}
|
||||
|
||||
private lateinit var binding: ActivityVideoEditBinding
|
||||
// Map photoData indexes to FFmpeg Session IDs
|
||||
private val sessionList: ArrayList<Long> = arrayListOf()
|
||||
|
@ -98,9 +111,13 @@ class VideoEditActivity : BaseThemedWithBarActivity() {
|
|||
|
||||
mediaPlayer.prepare()
|
||||
|
||||
|
||||
binding.muter.setOnClickListener {
|
||||
if(!binding.muter.isSelected) mediaPlayer.playerVolume = 0f
|
||||
else mediaPlayer.playerVolume = 1f
|
||||
else {
|
||||
mediaPlayer.playerVolume = 1f
|
||||
speed = 1
|
||||
}
|
||||
binding.muter.isSelected = !binding.muter.isSelected
|
||||
}
|
||||
|
||||
|
@ -130,6 +147,24 @@ class VideoEditActivity : BaseThemedWithBarActivity() {
|
|||
}
|
||||
|
||||
|
||||
|
||||
binding.speeder.setOnClickListener {
|
||||
AlertDialog.Builder(this).apply {
|
||||
setIcon(R.drawable.speed)
|
||||
setTitle(R.string.video_speed)
|
||||
setSingleChoiceItems(speedChoices.map { it.toString() + "x" }.toTypedArray(), speed) { dialog, which ->
|
||||
// update the selected item which is selected by the user so that it should be selected
|
||||
// when user opens the dialog next time and pass the instance to setSingleChoiceItems method
|
||||
speed = which
|
||||
|
||||
// when selected an item the dialog should be closed with the dismiss method
|
||||
dialog.dismiss()
|
||||
}
|
||||
setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
}.show()
|
||||
}
|
||||
|
||||
|
||||
val thumbInterval: Float? = duration?.div(7)
|
||||
|
||||
thumbInterval?.let {
|
||||
|
@ -188,7 +223,9 @@ class VideoEditActivity : BaseThemedWithBarActivity() {
|
|||
it[0] == 0f && it[2] == binding.videoRangeSeekBar.valueTo
|
||||
}
|
||||
val muted = binding.muter.isSelected
|
||||
return !muted && videoPositions
|
||||
val speedUnchanged = speed == 1
|
||||
|
||||
return !muted && videoPositions && speedUnchanged
|
||||
}
|
||||
|
||||
|
||||
|
@ -197,6 +234,7 @@ class VideoEditActivity : BaseThemedWithBarActivity() {
|
|||
.apply {
|
||||
putExtra(PhotoEditActivity.PICTURE_POSITION, videoPosition)
|
||||
putExtra(MUTED, binding.muter.isSelected)
|
||||
putExtra(SPEED, speed)
|
||||
putExtra(MODIFIED, !noEdits())
|
||||
putExtra(VIDEO_START, binding.videoRangeSeekBar.values.first())
|
||||
putExtra(VIDEO_END, binding.videoRangeSeekBar.values[2])
|
||||
|
@ -267,6 +305,9 @@ class VideoEditActivity : BaseThemedWithBarActivity() {
|
|||
companion object {
|
||||
const val VIDEO_TAG = "VideoEditTag"
|
||||
const val MUTED = "VideoEditMutedTag"
|
||||
const val SPEED = "VideoEditSpeedTag"
|
||||
// List of choices of speeds
|
||||
val speedChoices: List<Number> = listOf(0.5, 1, 2, 4, 8)
|
||||
const val VIDEO_START = "VideoEditVideoStartTag"
|
||||
const val VIDEO_END = "VideoEditVideoEndTag"
|
||||
const val MODIFIED = "VideoEditModifiedTag"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20.38,8.57l-1.23,1.85a8,8 0,0 1,-0.22 7.58L5.07,18A8,8 0,0 1,15.58 6.85l1.85,-1.23A10,10 0,0 0,3.35 19a2,2 0,0 0,1.72 1h13.85a2,2 0,0 0,1.74 -1,10 10,0 0,0 -0.27,-10.44zM10.59,15.41a2,2 0,0 0,2.83 0l5.66,-8.49 -8.49,5.66a2,2 0,0 0,0 2.83z"/>
|
||||
</vector>
|
|
@ -25,13 +25,27 @@
|
|||
android:layout_height="40dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:contentDescription="@string/add_comment"
|
||||
android:contentDescription="@string/mute_video"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="4dp"
|
||||
android:src="@drawable/selector_mute"
|
||||
app:layout_constraintBottom_toTopOf="@+id/thumbnail1"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/speeder"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:contentDescription="@string/video_speed"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="4dp"
|
||||
android:src="@drawable/speed"
|
||||
app:layout_constraintBottom_toTopOf="@+id/thumbnail1"
|
||||
app:layout_constraintStart_toEndOf="@+id/muter" />
|
||||
|
||||
<com.google.android.material.slider.RangeSlider
|
||||
android:id="@+id/videoRangeSeekBar"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -163,30 +163,44 @@
|
|||
app:layout_constraintTop_toTopOf="@+id/indicator"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible"
|
||||
tools:progress="30"
|
||||
android:id="@+id/encodeProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="64dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:indeterminate="false"
|
||||
android:max="100"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
android:id="@+id/encodeInfoCard"
|
||||
android:layout_marginEnd="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/encodeInfoText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:drawableStartCompat="@drawable/ic_heart"
|
||||
android:drawablePadding="6dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/encodeProgress"
|
||||
tools:text="Encoding..." />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_margin="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
tools:progress="30"
|
||||
android:id="@+id/encodeProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="false"
|
||||
android:max="100"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/encodeInfoText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="6dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/encodeProgress"
|
||||
tools:text="Encoding..." />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -269,6 +269,8 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
|
|||
<string name="encode_success">Encode success!</string>
|
||||
<string name="encode_progress">Encode %1$d%%</string>
|
||||
<string name="select_video_range">Select what to keep of the video</string>
|
||||
<string name="mute_video">Mute video</string>
|
||||
<string name="video_speed">Change video speed</string>
|
||||
<string name="still_encoding">One or more videos are still encoding. Wait for them to finish before uploading</string>
|
||||
<string name="new_post_shortcut_long">Create new post</string>
|
||||
<string name="new_post_shortcut_short">New post</string>
|
||||
|
|
|
@ -4257,6 +4257,11 @@
|
|||
<sha256 value="17bed05127c1a3521b5ded0ad97a863a5ec5d6232ee89e4393598e5fea639b73" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.cookpad.android.plugin.license-tools" name="com.cookpad.android.plugin.license-tools.gradle.plugin" version="1.2.8">
|
||||
<artifact name="com.cookpad.android.plugin.license-tools.gradle.plugin-1.2.8.pom">
|
||||
<sha256 value="93884f47eab85c0d4f615d5891600b79f489e472e69132c44e619822ac34f939" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.davemorrissey.labs" name="subsampling-scale-image-view-androidx" version="3.10.0">
|
||||
<artifact name="subsampling-scale-image-view-androidx-3.10.0.aar">
|
||||
<sha256 value="4ada2257a68615029ee5372dcfc9d400fb945434ccf68da6ef8c9b01a4022d13" origin="Generated by Gradle"/>
|
||||
|
@ -5338,6 +5343,14 @@
|
|||
<sha256 value="a776fef6cca4e715843bddd15a20eb8a47da44e47c6002c4a35c929bca3811d0" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.squareup.moshi" name="moshi" version="1.12.0">
|
||||
<artifact name="moshi-1.12.0.jar">
|
||||
<sha256 value="ee9091e1d1a5926fa9b4df2642c1fb7bb96aec08639b6219c19e0b8724d42475" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="moshi-1.12.0.module">
|
||||
<sha256 value="b86a93154471213195a442f85ca046e79a001c6d446c41d4d168936da856ebe2" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.squareup.moshi" name="moshi" version="1.9.2">
|
||||
<artifact name="moshi-1.9.2.jar">
|
||||
<sha256 value="48d73cc1fcef935635442700cf50a1174a3dcd2535c9fee320b70df0a83587bc" origin="Generated by Gradle"/>
|
||||
|
@ -5346,6 +5359,14 @@
|
|||
<sha256 value="6dfb37f452309d97561a64f4f20df967a3acd72d74fde43af6de75180881ac1c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.squareup.moshi" name="moshi-kotlin" version="1.12.0">
|
||||
<artifact name="moshi-kotlin-1.12.0.jar">
|
||||
<sha256 value="1c436c07c159cd1af032bb79351a48a98e7f781ac807cff8b5711a999b5666df" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="moshi-kotlin-1.12.0.module">
|
||||
<sha256 value="2a7bca66d6ccf16855cb5a0aa7c95158f688925a263efe4c204b237254861fa1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.squareup.moshi" name="moshi-kotlin" version="1.9.2">
|
||||
<artifact name="moshi-kotlin-1.9.2.jar">
|
||||
<sha256 value="97a91bd93234a5991a79ee67858b512bc63040031e694622547762b1448b6ed4" origin="Generated by Gradle"/>
|
||||
|
@ -5394,6 +5415,14 @@
|
|||
<sha256 value="1d2521621c0875123aa91311b2fe8edefd0ed93f66be6dfea18cc61bc5c99e36" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.squareup.okio" name="okio" version="2.10.0">
|
||||
<artifact name="okio-2.10.0.module">
|
||||
<sha256 value="11cbeabc3a765c9a803242fa2024a11853eb0865da536c4b05afdcdbb2346370" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="okio-jvm-2.10.0.jar">
|
||||
<sha256 value="a27f091d34aa452e37227e2cfa85809f29012a8ef2501a9b5a125a978e4fcbc1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.squareup.okio" name="okio" version="2.8.0">
|
||||
<artifact name="okio-2.8.0.module">
|
||||
<sha256 value="17baab7270389a5fa63ab12811864d0a00f381611bc4eb042fa1bd5918ed0965" origin="Generated by Gradle"/>
|
||||
|
@ -5578,6 +5607,14 @@
|
|||
<sha256 value="7e27939b6f837cb9820f12eed72d2d1df294273c099a920db9794c2293f32fbc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="gradle.plugin.com.cookpad.android.plugin" name="plugin" version="1.2.8">
|
||||
<artifact name="plugin-1.2.8.jar">
|
||||
<sha256 value="9015d1057a2b33081ef3324d434a82a94636ea01059da60c25c2cda65fd65d65" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="plugin-1.2.8.pom">
|
||||
<sha256 value="971f79090908bfd83150caddf79226c638cee4242d9e0cb76c70bc3d5f131499" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="info.androidhive" name="imagefilters" version="1.0.7">
|
||||
<artifact name="imagefilters-1.0.7.aar">
|
||||
<sha256 value="1230a2176bd95b4c0903e29b32cab71b24eccb3425a4da4a853a520b7af4a6ff" origin="Generated by Gradle"/>
|
||||
|
@ -7555,6 +7592,14 @@
|
|||
<sha256 value="3db67dafc422b9015e33cfdb3a4df9e8a6912de63c4b733197c8c189cdbc6d4a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.5.10">
|
||||
<artifact name="kotlin-stdlib-1.5.10.jar">
|
||||
<sha256 value="ca87c454cd3f2e60931f1803c59699d510d3b4b959cd7119296fb947581d722d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="kotlin-stdlib-1.5.10.pom">
|
||||
<sha256 value="305ad32461e1929a1cc32ba89861d9c41936a11189e6f486016eaf8b31c5bbcb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.5.30">
|
||||
<artifact name="kotlin-stdlib-1.5.30.jar">
|
||||
<sha256 value="c55608e9eb6df7327e74b21e271d324dc523cef31587b8d6d2393db08d6e000c" origin="Generated by Gradle"/>
|
||||
|
@ -7621,6 +7666,14 @@
|
|||
<sha256 value="98e59a445a3248f58811ce6782485de53fa77fc6f5adb3eb766a78b1231abd0a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.5.10">
|
||||
<artifact name="kotlin-stdlib-common-1.5.10.jar">
|
||||
<sha256 value="d958ce94beda85f865829fb95012804866db7d5246615fd71a2f5aabca3e7994" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="kotlin-stdlib-common-1.5.10.pom">
|
||||
<sha256 value="3bd55a1b94168bcf7cee3e506d52a688aaae36be0d0177973f6b266ed8e8be1c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.5.30">
|
||||
<artifact name="kotlin-stdlib-common-1.5.30.jar">
|
||||
<sha256 value="8eb3ac530a978422e0f8d0bba78ba2c628bec997dc2f1aa4ef8c5b854e3764b8" origin="Generated by Gradle"/>
|
||||
|
@ -8302,6 +8355,14 @@
|
|||
<sha256 value="66b54db68b2dc7ae2f4c5b3231b34fd0149af4f0a887a9dead9d4beba0b1b09c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.yaml" name="snakeyaml" version="1.29">
|
||||
<artifact name="snakeyaml-1.29.jar">
|
||||
<sha256 value="89c5f029811b08c878f0b81dbb05e9626624c1fda4087a26871101e499a217ab" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="snakeyaml-1.29.pom">
|
||||
<sha256 value="c8d3dddbed64b4b1cc0f7e85c04588cf0fd44e84e0dae930de1a2d8b985e681c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="stax" name="stax" version="1.2.0">
|
||||
<artifact name="stax-1.2.0.jar">
|
||||
<sha256 value="df6905a047b05e23bc91f03ba57ac2f87c1ddf83e048aa0e5bd13169d5ebf0d9" origin="Generated by Gradle"/>
|
||||
|
|
Loading…
Reference in New Issue