|
|
|
|
@ -16,7 +16,6 @@
|
|
|
|
|
package com.keylesspalace.tusky.components.compose |
|
|
|
|
|
|
|
|
|
import android.Manifest |
|
|
|
|
import android.app.Activity |
|
|
|
|
import android.app.ProgressDialog |
|
|
|
|
import android.content.Context |
|
|
|
|
import android.content.Intent |
|
|
|
|
@ -28,13 +27,13 @@ import android.net.Uri
|
|
|
|
|
import android.os.Build |
|
|
|
|
import android.os.Bundle |
|
|
|
|
import android.os.Parcelable |
|
|
|
|
import android.provider.MediaStore |
|
|
|
|
import android.util.Log |
|
|
|
|
import android.view.KeyEvent |
|
|
|
|
import android.view.MenuItem |
|
|
|
|
import android.view.View |
|
|
|
|
import android.view.ViewGroup |
|
|
|
|
import android.widget.* |
|
|
|
|
import androidx.activity.result.contract.ActivityResultContracts |
|
|
|
|
import androidx.activity.viewModels |
|
|
|
|
import androidx.annotation.ColorInt |
|
|
|
|
import androidx.annotation.StringRes |
|
|
|
|
@ -85,12 +84,12 @@ import kotlin.math.max
|
|
|
|
|
import kotlin.math.min |
|
|
|
|
|
|
|
|
|
class ComposeActivity : BaseActivity(), |
|
|
|
|
ComposeOptionsListener, |
|
|
|
|
ComposeAutoCompleteAdapter.AutocompletionProvider, |
|
|
|
|
OnEmojiSelectedListener, |
|
|
|
|
Injectable, |
|
|
|
|
InputConnectionCompat.OnCommitContentListener, |
|
|
|
|
ComposeScheduleView.OnTimeSetListener { |
|
|
|
|
ComposeOptionsListener, |
|
|
|
|
ComposeAutoCompleteAdapter.AutocompletionProvider, |
|
|
|
|
OnEmojiSelectedListener, |
|
|
|
|
Injectable, |
|
|
|
|
InputConnectionCompat.OnCommitContentListener, |
|
|
|
|
ComposeScheduleView.OnTimeSetListener { |
|
|
|
|
|
|
|
|
|
@Inject |
|
|
|
|
lateinit var viewModelFactory: ViewModelFactory |
|
|
|
|
@ -114,6 +113,21 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
private val maxUploadMediaNumber = 4 |
|
|
|
|
private var mediaCount = 0 |
|
|
|
|
|
|
|
|
|
private val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { success -> |
|
|
|
|
if (success) { |
|
|
|
|
pickMedia(photoUploadUri!!) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
private val pickMediaFile = registerForActivityResult(PickMediaFiles()) { uris -> |
|
|
|
|
if (mediaCount + uris.size > maxUploadMediaNumber) { |
|
|
|
|
Toast.makeText(this, resources.getQuantityString(R.plurals.error_upload_max_media_reached, maxUploadMediaNumber, maxUploadMediaNumber), Toast.LENGTH_SHORT).show() |
|
|
|
|
} else { |
|
|
|
|
uris.forEach { uri -> |
|
|
|
|
pickMedia(uri) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override fun onCreate(savedInstanceState: Bundle?) { |
|
|
|
|
super.onCreate(savedInstanceState) |
|
|
|
|
|
|
|
|
|
@ -130,16 +144,16 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
|
|
|
|
|
setupAvatar(preferences, activeAccount) |
|
|
|
|
val mediaAdapter = MediaPreviewAdapter( |
|
|
|
|
this, |
|
|
|
|
onAddCaption = { item -> |
|
|
|
|
makeCaptionDialog(item.description, item.uri) { newDescription -> |
|
|
|
|
viewModel.updateDescription(item.localId, newDescription) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
onRemove = this::removeMediaFromQueue |
|
|
|
|
this, |
|
|
|
|
onAddCaption = { item -> |
|
|
|
|
makeCaptionDialog(item.description, item.uri) { newDescription -> |
|
|
|
|
viewModel.updateDescription(item.localId, newDescription) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
onRemove = this::removeMediaFromQueue |
|
|
|
|
) |
|
|
|
|
binding.composeMediaPreviewBar.layoutManager = |
|
|
|
|
LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) |
|
|
|
|
LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) |
|
|
|
|
binding.composeMediaPreviewBar.adapter = mediaAdapter |
|
|
|
|
binding.composeMediaPreviewBar.itemAnimator = null |
|
|
|
|
|
|
|
|
|
@ -255,11 +269,11 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
binding.composeEditField.setOnKeyListener { _, keyCode, event -> this.onKeyDown(keyCode, event) } |
|
|
|
|
|
|
|
|
|
binding.composeEditField.setAdapter( |
|
|
|
|
ComposeAutoCompleteAdapter( |
|
|
|
|
this, |
|
|
|
|
preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false), |
|
|
|
|
preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) |
|
|
|
|
) |
|
|
|
|
ComposeAutoCompleteAdapter( |
|
|
|
|
this, |
|
|
|
|
preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false), |
|
|
|
|
preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false) |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
binding.composeEditField.setTokenizer(ComposeTokenizer()) |
|
|
|
|
|
|
|
|
|
@ -275,7 +289,7 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
|
|
|
|
|
// work around Android platform bug -> https://issuetracker.google.com/issues/67102093 |
|
|
|
|
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O |
|
|
|
|
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) { |
|
|
|
|
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) { |
|
|
|
|
binding.composeEditField.setLayerType(View.LAYER_TYPE_SOFTWARE, null) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -390,13 +404,13 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
|
|
|
|
|
val animateAvatars = preferences.getBoolean("animateGifAvatars", false) |
|
|
|
|
loadAvatar( |
|
|
|
|
activeAccount.profilePictureUrl, |
|
|
|
|
binding.composeAvatar, |
|
|
|
|
avatarSize / 8, |
|
|
|
|
animateAvatars |
|
|
|
|
activeAccount.profilePictureUrl, |
|
|
|
|
binding.composeAvatar, |
|
|
|
|
avatarSize / 8, |
|
|
|
|
animateAvatars |
|
|
|
|
) |
|
|
|
|
binding.composeAvatar.contentDescription = getString(R.string.compose_active_account_description, |
|
|
|
|
activeAccount.fullName) |
|
|
|
|
activeAccount.fullName) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun replaceTextAtCaret(text: CharSequence) { |
|
|
|
|
@ -602,10 +616,10 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
addMediaBehavior.removeBottomSheetCallback(this) |
|
|
|
|
if (ContextCompat.checkSelfPermission(this@ComposeActivity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { |
|
|
|
|
ActivityCompat.requestPermissions(this@ComposeActivity, |
|
|
|
|
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), |
|
|
|
|
PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE) |
|
|
|
|
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), |
|
|
|
|
PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE) |
|
|
|
|
} else { |
|
|
|
|
initiateMediaPicking() |
|
|
|
|
pickMediaFile.launch(true) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -620,7 +634,7 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
addMediaBehavior.state = BottomSheetBehavior.STATE_COLLAPSED |
|
|
|
|
val instanceParams = viewModel.instanceParams.value!! |
|
|
|
|
showAddPollDialog(this, viewModel.poll.value, instanceParams.pollMaxOptions, |
|
|
|
|
instanceParams.pollMaxLength, viewModel::updatePoll) |
|
|
|
|
instanceParams.pollMaxLength, viewModel::updatePoll) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun setupPollView() { |
|
|
|
|
@ -740,8 +754,8 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
} else if (characterCount <= maximumTootCharacters) { |
|
|
|
|
if (viewModel.media.value!!.isNotEmpty()) { |
|
|
|
|
finishingUploadDialog = ProgressDialog.show( |
|
|
|
|
this, getString(R.string.dialog_title_finishing_media_upload), |
|
|
|
|
getString(R.string.dialog_message_uploading_media), true, true) |
|
|
|
|
this, getString(R.string.dialog_title_finishing_media_upload), |
|
|
|
|
getString(R.string.dialog_message_uploading_media), true, true) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
viewModel.sendStatus(contentText, spoilerText).observe(this, { |
|
|
|
|
@ -755,20 +769,20 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, |
|
|
|
|
grantResults: IntArray) { |
|
|
|
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { |
|
|
|
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults) |
|
|
|
|
|
|
|
|
|
if (requestCode == PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE) { |
|
|
|
|
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { |
|
|
|
|
initiateMediaPicking() |
|
|
|
|
pickMediaFile.launch(true) |
|
|
|
|
} else { |
|
|
|
|
val bar = Snackbar.make(binding.activityCompose, R.string.error_media_upload_permission, |
|
|
|
|
Snackbar.LENGTH_SHORT).apply { |
|
|
|
|
|
|
|
|
|
Snackbar.make(binding.activityCompose, R.string.error_media_upload_permission, |
|
|
|
|
Snackbar.LENGTH_SHORT).apply { |
|
|
|
|
setAction(R.string.action_retry) { onMediaPick() } |
|
|
|
|
//necessary so snackbar is shown over everything |
|
|
|
|
view.elevation = resources.getDimension(R.dimen.compose_activity_snackbar_elevation) |
|
|
|
|
show() |
|
|
|
|
} |
|
|
|
|
bar.setAction(R.string.action_retry) { onMediaPick() } |
|
|
|
|
//necessary so snackbar is shown over everything |
|
|
|
|
bar.view.elevation = resources.getDimension(R.dimen.compose_activity_snackbar_elevation) |
|
|
|
|
bar.show() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -776,50 +790,32 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
private fun initiateCameraApp() { |
|
|
|
|
addMediaBehavior.state = BottomSheetBehavior.STATE_COLLAPSED |
|
|
|
|
|
|
|
|
|
// We don't need to ask for permission in this case, because the used calls require |
|
|
|
|
// android.permission.WRITE_EXTERNAL_STORAGE only on SDKs *older* than Kitkat, which was |
|
|
|
|
// way before permission dialogues have been introduced. |
|
|
|
|
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) |
|
|
|
|
if (intent.resolveActivity(packageManager) != null) { |
|
|
|
|
val photoFile: File = try { |
|
|
|
|
createNewImageFile(this) |
|
|
|
|
} catch (ex: IOException) { |
|
|
|
|
displayTransientError(R.string.error_media_upload_opening) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Continue only if the File was successfully created |
|
|
|
|
photoUploadUri = FileProvider.getUriForFile(this, |
|
|
|
|
BuildConfig.APPLICATION_ID + ".fileprovider", |
|
|
|
|
photoFile) |
|
|
|
|
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUploadUri) |
|
|
|
|
startActivityForResult(intent, MEDIA_TAKE_PHOTO_RESULT) |
|
|
|
|
val photoFile: File = try { |
|
|
|
|
createNewImageFile(this) |
|
|
|
|
} catch (ex: IOException) { |
|
|
|
|
displayTransientError(R.string.error_media_upload_opening) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun initiateMediaPicking() { |
|
|
|
|
val intent = Intent(Intent.ACTION_GET_CONTENT) |
|
|
|
|
intent.addCategory(Intent.CATEGORY_OPENABLE) |
|
|
|
|
|
|
|
|
|
val mimeTypes = arrayOf("image/*", "video/*", "audio/*") |
|
|
|
|
intent.type = "*/*" |
|
|
|
|
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes) |
|
|
|
|
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) |
|
|
|
|
startActivityForResult(intent, MEDIA_PICK_RESULT) |
|
|
|
|
// Continue only if the File was successfully created |
|
|
|
|
photoUploadUri = FileProvider.getUriForFile(this, |
|
|
|
|
BuildConfig.APPLICATION_ID + ".fileprovider", |
|
|
|
|
photoFile) |
|
|
|
|
takePicture.launch(photoUploadUri) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun enableButton(button: ImageButton, clickable: Boolean, colorActive: Boolean) { |
|
|
|
|
button.isEnabled = clickable |
|
|
|
|
ThemeUtils.setDrawableTint(this, button.drawable, |
|
|
|
|
if (colorActive) android.R.attr.textColorTertiary |
|
|
|
|
else R.attr.textColorDisabled) |
|
|
|
|
if (colorActive) android.R.attr.textColorTertiary |
|
|
|
|
else R.attr.textColorDisabled) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun enablePollButton(enable: Boolean) { |
|
|
|
|
binding.addPollTextActionTextView.isEnabled = enable |
|
|
|
|
val textColor = ThemeUtils.getColor(this, |
|
|
|
|
if (enable) android.R.attr.textColorTertiary |
|
|
|
|
else R.attr.textColorDisabled) |
|
|
|
|
if (enable) android.R.attr.textColorTertiary |
|
|
|
|
else R.attr.textColorDisabled) |
|
|
|
|
binding.addPollTextActionTextView.setTextColor(textColor) |
|
|
|
|
binding.addPollTextActionTextView.compoundDrawablesRelative[0].colorFilter = PorterDuffColorFilter(textColor, PorterDuff.Mode.SRC_IN) |
|
|
|
|
} |
|
|
|
|
@ -828,31 +824,6 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
viewModel.removeMediaFromQueue(item) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { |
|
|
|
|
super.onActivityResult(requestCode, resultCode, intent) |
|
|
|
|
if (resultCode == Activity.RESULT_OK && requestCode == MEDIA_PICK_RESULT && intent != null) { |
|
|
|
|
if (intent.data != null) { |
|
|
|
|
// Single media, upload it and done. |
|
|
|
|
pickMedia(intent.data!!) |
|
|
|
|
} else if (intent.clipData != null) { |
|
|
|
|
val clipData = intent.clipData!! |
|
|
|
|
val count = clipData.itemCount |
|
|
|
|
if (mediaCount + count > maxUploadMediaNumber) { |
|
|
|
|
// check if exist media + upcoming media > 4, then prob error message. |
|
|
|
|
Toast.makeText(this, resources.getQuantityString(R.plurals.error_upload_max_media_reached, maxUploadMediaNumber, maxUploadMediaNumber), Toast.LENGTH_SHORT).show() |
|
|
|
|
} else { |
|
|
|
|
// if not grater then 4, upload all multiple media. |
|
|
|
|
for (i in 0 until count) { |
|
|
|
|
val imageUri = clipData.getItemAt(i).getUri() |
|
|
|
|
pickMedia(imageUri) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else if (resultCode == Activity.RESULT_OK && requestCode == MEDIA_TAKE_PHOTO_RESULT) { |
|
|
|
|
pickMedia(photoUploadUri!!) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private fun pickMedia(uri: Uri, contentInfoCompat: InputContentInfoCompat? = null) { |
|
|
|
|
withLifecycleContext { |
|
|
|
|
viewModel.pickMedia(uri).observe { exceptionOrItem -> |
|
|
|
|
@ -908,9 +879,9 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
override fun onBackPressed() { |
|
|
|
|
// Acting like a teen: deliberately ignoring parent. |
|
|
|
|
if (composeOptionsBehavior.state == BottomSheetBehavior.STATE_EXPANDED || |
|
|
|
|
addMediaBehavior.state == BottomSheetBehavior.STATE_EXPANDED || |
|
|
|
|
emojiBehavior.state == BottomSheetBehavior.STATE_EXPANDED || |
|
|
|
|
scheduleBehavior.state == BottomSheetBehavior.STATE_EXPANDED) { |
|
|
|
|
addMediaBehavior.state == BottomSheetBehavior.STATE_EXPANDED || |
|
|
|
|
emojiBehavior.state == BottomSheetBehavior.STATE_EXPANDED || |
|
|
|
|
scheduleBehavior.state == BottomSheetBehavior.STATE_EXPANDED) { |
|
|
|
|
composeOptionsBehavior.state = BottomSheetBehavior.STATE_HIDDEN |
|
|
|
|
addMediaBehavior.state = BottomSheetBehavior.STATE_HIDDEN |
|
|
|
|
emojiBehavior.state = BottomSheetBehavior.STATE_HIDDEN |
|
|
|
|
@ -945,12 +916,12 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
val contentWarning = binding.composeContentWarningField.text.toString() |
|
|
|
|
if (viewModel.didChange(contentText, contentWarning)) { |
|
|
|
|
AlertDialog.Builder(this) |
|
|
|
|
.setMessage(R.string.compose_save_draft) |
|
|
|
|
.setPositiveButton(R.string.action_save) { _, _ -> |
|
|
|
|
saveDraftAndFinish(contentText, contentWarning) |
|
|
|
|
} |
|
|
|
|
.setNegativeButton(R.string.action_delete) { _, _ -> deleteDraftAndFinish() } |
|
|
|
|
.show() |
|
|
|
|
.setMessage(R.string.compose_save_draft) |
|
|
|
|
.setPositiveButton(R.string.action_save) { _, _ -> |
|
|
|
|
saveDraftAndFinish(contentText, contentWarning) |
|
|
|
|
} |
|
|
|
|
.setNegativeButton(R.string.action_delete) { _, _ -> deleteDraftAndFinish() } |
|
|
|
|
.show() |
|
|
|
|
} else { |
|
|
|
|
finishWithoutSlideOutAnimation() |
|
|
|
|
} |
|
|
|
|
@ -982,13 +953,13 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
data class QueuedMedia( |
|
|
|
|
val localId: Long, |
|
|
|
|
val uri: Uri, |
|
|
|
|
val type: Type, |
|
|
|
|
val mediaSize: Long, |
|
|
|
|
val uploadPercent: Int = 0, |
|
|
|
|
val id: String? = null, |
|
|
|
|
val description: String? = null |
|
|
|
|
val localId: Long, |
|
|
|
|
val uri: Uri, |
|
|
|
|
val type: Type, |
|
|
|
|
val mediaSize: Long, |
|
|
|
|
val uploadPercent: Int = 0, |
|
|
|
|
val id: String? = null, |
|
|
|
|
val description: String? = null |
|
|
|
|
) { |
|
|
|
|
enum class Type { |
|
|
|
|
IMAGE, VIDEO, AUDIO; |
|
|
|
|
@ -1011,31 +982,29 @@ class ComposeActivity : BaseActivity(),
|
|
|
|
|
|
|
|
|
|
@Parcelize |
|
|
|
|
data class ComposeOptions( |
|
|
|
|
// Let's keep fields var until all consumers are Kotlin |
|
|
|
|
var scheduledTootId: String? = null, |
|
|
|
|
var draftId: Int? = null, |
|
|
|
|
var tootText: String? = null, |
|
|
|
|
var mediaUrls: List<String>? = null, |
|
|
|
|
var mediaDescriptions: List<String>? = null, |
|
|
|
|
var mentionedUsernames: Set<String>? = null, |
|
|
|
|
var inReplyToId: String? = null, |
|
|
|
|
var replyVisibility: Status.Visibility? = null, |
|
|
|
|
var visibility: Status.Visibility? = null, |
|
|
|
|
var contentWarning: String? = null, |
|
|
|
|
var replyingStatusAuthor: String? = null, |
|
|
|
|
var replyingStatusContent: String? = null, |
|
|
|
|
var mediaAttachments: List<Attachment>? = null, |
|
|
|
|
var draftAttachments: List<DraftAttachment>? = null, |
|
|
|
|
var scheduledAt: String? = null, |
|
|
|
|
var sensitive: Boolean? = null, |
|
|
|
|
var poll: NewPoll? = null, |
|
|
|
|
var modifiedInitialState: Boolean? = null |
|
|
|
|
// Let's keep fields var until all consumers are Kotlin |
|
|
|
|
var scheduledTootId: String? = null, |
|
|
|
|
var draftId: Int? = null, |
|
|
|
|
var tootText: String? = null, |
|
|
|
|
var mediaUrls: List<String>? = null, |
|
|
|
|
var mediaDescriptions: List<String>? = null, |
|
|
|
|
var mentionedUsernames: Set<String>? = null, |
|
|
|
|
var inReplyToId: String? = null, |
|
|
|
|
var replyVisibility: Status.Visibility? = null, |
|
|
|
|
var visibility: Status.Visibility? = null, |
|
|
|
|
var contentWarning: String? = null, |
|
|
|
|
var replyingStatusAuthor: String? = null, |
|
|
|
|
var replyingStatusContent: String? = null, |
|
|
|
|
var mediaAttachments: List<Attachment>? = null, |
|
|
|
|
var draftAttachments: List<DraftAttachment>? = null, |
|
|
|
|
var scheduledAt: String? = null, |
|
|
|
|
var sensitive: Boolean? = null, |
|
|
|
|
var poll: NewPoll? = null, |
|
|
|
|
var modifiedInitialState: Boolean? = null |
|
|
|
|
) : Parcelable |
|
|
|
|
|
|
|
|
|
companion object { |
|
|
|
|
private const val TAG = "ComposeActivity" // logging tag |
|
|
|
|
private const val MEDIA_PICK_RESULT = 1 |
|
|
|
|
private const val MEDIA_TAKE_PHOTO_RESULT = 2 |
|
|
|
|
private const val PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1 |
|
|
|
|
|
|
|
|
|
internal const val COMPOSE_OPTIONS_EXTRA = "COMPOSE_OPTIONS" |
|
|
|
|
|