129 lines
4.3 KiB
Kotlin
129 lines
4.3 KiB
Kotlin
package jp.juggler.subwaytooter.util
|
|
|
|
import android.provider.MediaStore
|
|
import androidx.appcompat.app.AppCompatActivity
|
|
import jp.juggler.subwaytooter.R
|
|
import jp.juggler.subwaytooter.dialog.actionsDialog
|
|
import jp.juggler.subwaytooter.kJson
|
|
import jp.juggler.util.coroutine.launchAndShowError
|
|
import jp.juggler.util.data.UriAndType
|
|
import jp.juggler.util.log.LogCategory
|
|
import kotlinx.serialization.Serializable
|
|
import kotlinx.serialization.encodeToString
|
|
|
|
class AttachmentPicker(
|
|
val activity: AppCompatActivity,
|
|
val callback: Callback,
|
|
) {
|
|
companion object {
|
|
private val log = LogCategory("AttachmentPicker")
|
|
|
|
private const val PERMISSION_REQUEST_CODE = 1
|
|
}
|
|
|
|
// callback after media selected
|
|
interface Callback {
|
|
suspend fun onPickAttachment(item: UriAndType)
|
|
suspend fun onPickCustomThumbnail(attachmentId: String?, src: UriAndType?)
|
|
}
|
|
|
|
// actions after permission granted
|
|
enum class AfterPermission { Attachment, CustomThumbnail, }
|
|
|
|
@Serializable
|
|
data class States(
|
|
var customThumbnailTargetId: String? = null,
|
|
)
|
|
|
|
private var states = States()
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// activity result handlers
|
|
|
|
private val visualMediaPickerThumbnail = VisualMediaPickerCompat {
|
|
callback.onPickCustomThumbnail(states.customThumbnailTargetId, it?.firstOrNull())
|
|
}
|
|
|
|
private val visualMediaPickerAttachment = VisualMediaPickerCompat { it?.pickAll() }
|
|
|
|
private val audioPicker = AudioPicker { it?.pickAll() }
|
|
|
|
private val cameraOpener = CameraOpener { callback.onPickAttachment(it) }
|
|
|
|
private val captureOpener = CaptureOpener { callback.onPickAttachment(it) }
|
|
|
|
init {
|
|
visualMediaPickerAttachment.register(activity)
|
|
visualMediaPickerThumbnail.register(activity)
|
|
cameraOpener.register(activity)
|
|
audioPicker.register(activity)
|
|
captureOpener.register(activity)
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// states
|
|
|
|
fun reset() {
|
|
cameraOpener.reset()
|
|
}
|
|
|
|
fun encodeState(): String {
|
|
val encoded = kJson.encodeToString(states)
|
|
val decoded = kJson.decodeFromString<States>(encoded)
|
|
log.d("encodeState: states=$states, encoded=$encoded, decoded=$decoded")
|
|
return encoded
|
|
}
|
|
|
|
fun restoreState(encoded: String) {
|
|
states = kJson.decodeFromString(encoded)
|
|
log.d("restoreState: states=$states, encoded=$encoded")
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
fun openPicker() {
|
|
activity.run {
|
|
launchAndShowError {
|
|
actionsDialog {
|
|
action(getString(R.string.pick_images_or_video)) {
|
|
visualMediaPickerAttachment.open(
|
|
multiple = true,
|
|
allowVideo = true,
|
|
)
|
|
}
|
|
action(getString(R.string.pick_audios)) {
|
|
audioPicker.open()
|
|
}
|
|
action(getString(R.string.image_capture)) {
|
|
cameraOpener.open()
|
|
}
|
|
action(getString(R.string.video_capture)) {
|
|
captureOpener.open(
|
|
MediaStore.ACTION_VIDEO_CAPTURE,
|
|
"can't open video capture app."
|
|
)
|
|
}
|
|
action(getString(R.string.voice_capture)) {
|
|
captureOpener.open(
|
|
MediaStore.Audio.Media.RECORD_SOUND_ACTION,
|
|
"can't open voice capture app."
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private suspend fun List<UriAndType>.pickAll() {
|
|
forEach { callback.onPickAttachment(it) }
|
|
}
|
|
|
|
// ActPostAttachmentから呼ばれる
|
|
fun openThumbnailPicker(pa: PostAttachment) {
|
|
states.customThumbnailTargetId =
|
|
pa.attachment?.id?.toString()
|
|
?: error("attachmentId is null")
|
|
visualMediaPickerThumbnail.open()
|
|
}
|
|
}
|