SubwayTooter-Android-App/app/src/main/java/jp/juggler/subwaytooter/util/AttachmentPicker.kt

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()
}
}