From d04ad581ead4d85e84d38b0cc7a143471884e677 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 14 Jun 2024 17:43:18 -0400 Subject: [PATCH 01/15] Add constant for EXTRA_CONTENT_FROM_AI --- .../org/wordpress/android/ui/posts/EditPostActivityConstants.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivityConstants.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivityConstants.kt index 7fe36f345e5a..087fddeab582 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivityConstants.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivityConstants.kt @@ -26,6 +26,7 @@ object EditPostActivityConstants{ const val EXTRA_PAGE_TEMPLATE = "pageTemplate" const val EXTRA_PROMPT_ID = "extraPromptId" const val EXTRA_ENTRY_POINT = "extraEntryPoint" + const val EXTRA_CONTENT_FROM_AI = "extra_content_from_ai" const val STATE_KEY_EDITOR_FRAGMENT = "editorFragment" const val STATE_KEY_DROPPED_MEDIA_URIS = "stateKeyDroppedMediaUri" const val STATE_KEY_POST_LOCAL_ID = "stateKeyPostModelLocalId" From 82325b3712917947b1e822a426635f2ad456e3bc Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Fri, 14 Jun 2024 17:44:26 -0400 Subject: [PATCH 02/15] Add new method to launch editPost with content from AI --- .../android/ui/ActivityLauncher.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index 6f1f81e55dfc..c026e1a6943a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -953,6 +953,26 @@ public static void viewBlogAdmin(Context context, SiteModel site) { openUrlExternal(context, site.getAdminUrl()); } + public static void addNewPostWithContentFromAIForResult( + Activity activity, + SiteModel site, + boolean isPromo, + PagePostCreationSourcesDetail source, + final String content + ) { + if (site == null) { + return; + } + + Intent intent = new Intent(activity, EditPostActivity.class); + intent.putExtra(WordPress.SITE, site); + intent.putExtra(EditPostActivityConstants.EXTRA_IS_PAGE, false); + intent.putExtra(EditPostActivityConstants.EXTRA_IS_PROMO, isPromo); + intent.putExtra(AnalyticsUtils.EXTRA_CREATION_SOURCE_DETAIL, source); + intent.putExtra(EditPostActivityConstants.EXTRA_CONTENT_FROM_AI, content); + activity.startActivityForResult(intent, RequestCodes.EDIT_POST); + } + public static void addNewPostForResult( Activity activity, SiteModel site, From 7af229180d6ff445d90389883ddbefdff813f761 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:01:46 -0400 Subject: [PATCH 03/15] Add state key for voice to content and update extra name --- .../wordpress/android/ui/posts/EditPostActivityConstants.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivityConstants.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivityConstants.kt index 087fddeab582..77cf11f42b7f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivityConstants.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivityConstants.kt @@ -26,7 +26,7 @@ object EditPostActivityConstants{ const val EXTRA_PAGE_TEMPLATE = "pageTemplate" const val EXTRA_PROMPT_ID = "extraPromptId" const val EXTRA_ENTRY_POINT = "extraEntryPoint" - const val EXTRA_CONTENT_FROM_AI = "extra_content_from_ai" + const val EXTRA_VOICE_CONTENT = "extra_voice_content" const val STATE_KEY_EDITOR_FRAGMENT = "editorFragment" const val STATE_KEY_DROPPED_MEDIA_URIS = "stateKeyDroppedMediaUri" const val STATE_KEY_POST_LOCAL_ID = "stateKeyPostModelLocalId" @@ -41,4 +41,5 @@ object EditPostActivityConstants{ const val STATE_KEY_MEDIA_CAPTURE_PATH = "stateKeyMediaCapturePath" const val STATE_KEY_UNDO = "stateKeyUndo" const val STATE_KEY_REDO = "stateKeyRedo" + const val STATE_KEY_IS_VOICE_CONTENT_SET = "stateKeyIsVoiceContentSet" } From c0236703a4880957932857f93a1816849bd4dc54 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:02:27 -0400 Subject: [PATCH 04/15] Add updateContent as the passthrough to the container for voice to content --- .../org/wordpress/android/editor/EditorFragmentAbstract.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/editor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java b/libs/editor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java index 1a809ad11c6a..18255e7f90d3 100644 --- a/libs/editor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java +++ b/libs/editor/src/main/java/org/wordpress/android/editor/EditorFragmentAbstract.java @@ -57,6 +57,7 @@ public abstract Pair getTitleAndContent(CharSequence public abstract void onUndoPressed(); public abstract void onRedoPressed(); + public abstract void updateContent(CharSequence text); public enum MediaType { From 27c7569f449b159f4dba17ea142276d16ed53cfe Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:02:58 -0400 Subject: [PATCH 05/15] Implement updateContent() for voice to content - GB only --- .../wordpress/android/editor/AztecEditorFragment.java | 5 +++++ .../editor/gutenberg/GutenbergEditorFragment.java | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/libs/editor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java b/libs/editor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java index 17537f28195d..ee028d2d8ebd 100644 --- a/libs/editor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java +++ b/libs/editor/src/main/java/org/wordpress/android/editor/AztecEditorFragment.java @@ -1690,6 +1690,11 @@ public void showNotice(String message) { @Override public void onRedoPressed() { } + @Override + public void updateContent(@Nullable CharSequence text) { + // not implemented for Aztec + } + private void onMediaTapped(@NonNull final AztecAttributes attrs, int naturalWidth, int naturalHeight, final MediaType mediaType) { if (mediaType == null || !isAdded()) { diff --git a/libs/editor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java b/libs/editor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java index 38504687b0d9..859dadef8272 100644 --- a/libs/editor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java +++ b/libs/editor/src/main/java/org/wordpress/android/editor/gutenberg/GutenbergEditorFragment.java @@ -1096,6 +1096,17 @@ public void setContent(CharSequence text) { getGutenbergContainerFragment().setContent(postContent); } + @Override + public void updateContent(@Nullable CharSequence text) { + if (text == null) { + text = ""; + } + + if (getGutenbergContainerFragment() != null) { + getGutenbergContainerFragment().onContentUpdate(text.toString()); + } + } + public void setJetpackSsoEnabled(boolean jetpackSsoEnabled) { mIsJetpackSsoEnabled = jetpackSsoEnabled; } From 7029d428b4c8d3e9ae1aebb9cc9f98e302d5ae6c Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:03:44 -0400 Subject: [PATCH 06/15] Update to reflect refactored intent extra name --- .../main/java/org/wordpress/android/ui/ActivityLauncher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java index c026e1a6943a..1c16c014490a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncher.java @@ -969,7 +969,7 @@ public static void addNewPostWithContentFromAIForResult( intent.putExtra(EditPostActivityConstants.EXTRA_IS_PAGE, false); intent.putExtra(EditPostActivityConstants.EXTRA_IS_PROMO, isPromo); intent.putExtra(AnalyticsUtils.EXTRA_CREATION_SOURCE_DETAIL, source); - intent.putExtra(EditPostActivityConstants.EXTRA_CONTENT_FROM_AI, content); + intent.putExtra(EditPostActivityConstants.EXTRA_VOICE_CONTENT, content); activity.startActivityForResult(intent, RequestCodes.EDIT_POST); } From 1ac5297368dea52c16fb789a7b6994451105d7c8 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:04:36 -0400 Subject: [PATCH 07/15] Implement updateVoiceContentIfNeeded to updateContent if this is a voice to content request --- .../android/ui/posts/EditPostActivity.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt index 16db759bfb31..6973648afc02 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt @@ -309,6 +309,7 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm private var postLoadingState: PostLoadingState = PostLoadingState.NONE private var isXPostsCapable: Boolean? = null private var onGetSuggestionResult: Consumer? = null + private var isVoiceContentSet = false // For opening the context menu after permissions have been granted private var menuView: View? = null @@ -717,6 +718,7 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm } isNewPost = state.getBoolean(EditPostActivityConstants.STATE_KEY_IS_NEW_POST, false) + isVoiceContentSet = state.getBoolean(EditPostActivityConstants.STATE_KEY_IS_NEW_POST, false) updatePostLoadingAndDialogState( fromInt( state.getInt(EditPostActivityConstants.STATE_KEY_POST_LOADING_STATE, 0) @@ -1185,6 +1187,7 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm } outState.putInt(EditPostActivityConstants.STATE_KEY_POST_LOADING_STATE, postLoadingState.value) outState.putBoolean(EditPostActivityConstants.STATE_KEY_IS_NEW_POST, isNewPost) + outState.putBoolean(EditPostActivityConstants.STATE_KEY_IS_VOICE_CONTENT_SET, isVoiceContentSet) outState.putBoolean( EditPostActivityConstants.STATE_KEY_IS_PHOTO_PICKER_VISIBLE, editorPhotoPicker?.isPhotoPickerShowing() ?: false @@ -3526,6 +3529,25 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm // Start VM, load prompt and populate Editor with content after edit IS ready. val promptId: Int = intent.getIntExtra(EditPostActivityConstants.EXTRA_PROMPT_ID, -1) editorBloggingPromptsViewModel.start(siteModel, promptId) + + updateVoiceContentIfNeeded() + } + + private fun updateVoiceContentIfNeeded() { + // Set the voiceToContent content if it exits and this is a GB Editor fragment - do this only once + val hasVoiceContent = intent.hasExtra(EditPostActivityConstants.EXTRA_VOICE_CONTENT) + if (isNewPost && hasVoiceContent && !isVoiceContentSet) { + editorFragment?.let { + if (it is GutenbergEditorFragment) { + val gutenbergFragment = editorFragment as GutenbergEditorFragment + val content = intent.getStringExtra(EditPostActivityConstants.EXTRA_VOICE_CONTENT) + content?.let { + isVoiceContentSet = true + gutenbergFragment.updateContent(content) + } + } + } + } } private fun logTemplateSelection() { From aa5eb48a8d26c5d0668367909b60e1defbb4849d Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:05:09 -0400 Subject: [PATCH 08/15] Holds VoiceToContent actions and events --- .../android/ui/voicetocontent/VoiceToContentActionEvent.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt new file mode 100644 index 000000000000..30b2c0353036 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt @@ -0,0 +1,7 @@ +package org.wordpress.android.ui.voicetocontent + +import org.wordpress.android.fluxc.model.SiteModel + +sealed class VoiceToContentActionEvent { + data class LaunchEditPost(val site: SiteModel, val content: String) : VoiceToContentActionEvent() +} From b719175000a076863cee3ef73934f3113196bb98 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:06:03 -0400 Subject: [PATCH 09/15] Observe actionEvents from the viewModel, implement launchEditPost --- .../VoiceToContentDialogFragment.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt index 7375ae03ffc2..9fba53c26c63 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt @@ -24,7 +24,9 @@ import android.widget.FrameLayout import androidx.compose.material.ExperimentalMaterialApi import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog +import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.ActivityNavigator +import org.wordpress.android.ui.PagePostCreationSourcesDetail import javax.inject.Inject @AndroidEntryPoint @@ -116,6 +118,12 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { viewModel.onIneligibleForVoiceToContent.observe(viewLifecycleOwner) { url -> launchIneligibleForVoiceToContent(url) } + + viewModel.actionEvent.observe(viewLifecycleOwner) { actionEvent -> + when(actionEvent) { + is VoiceToContentActionEvent.LaunchEditPost -> launchEditPost(actionEvent) + } + } } private val requestMultiplePermissionsLauncher = registerForActivityResult( @@ -157,6 +165,18 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { } } + private fun launchEditPost(event: VoiceToContentActionEvent.LaunchEditPost) { + activity?.let { + ActivityLauncher.addNewPostWithContentFromAIForResult( + it, + event.site, + false, + PagePostCreationSourcesDetail.POST_FROM_MY_SITE, + event.content + ) + } + } + companion object { const val TAG = "voice_to_content_fragment_tag" From e863a33d38f1b47be6eef02e4bc0c648426242c0 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:06:54 -0400 Subject: [PATCH 10/15] Create actionEvents liveData and post launchEditPost on success of processing v2c --- .../android/ui/voicetocontent/VoiceToContentViewModel.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index 68fb9d361a32..f879f6c704e3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -60,6 +60,9 @@ class VoiceToContentViewModel @Inject constructor( private val _isCancelableOutsideTouch = MutableLiveData(true) val isCancelableOutsideTouch: LiveData get() = _isCancelableOutsideTouch + private val _actionEvent = MutableLiveData() + val actionEvent = _actionEvent as LiveData + private var isStarted = false private val _state = MutableStateFlow(VoiceToContentUiState( @@ -182,7 +185,7 @@ class VoiceToContentViewModel @Inject constructor( when (val result = voiceToContentUseCase.execute(site, file)) { is VoiceToContentResult.Failure -> result.transitionToError() is VoiceToContentResult.Success -> - Log.i(javaClass.simpleName, "***=> result is ${result.content}") + _actionEvent.postValue(VoiceToContentActionEvent.LaunchEditPost(site, result.content)) } _dismiss.postValue(Unit) } From b22898ce85909547b0e853b7aa6700dca79c12bd Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:25:47 -0400 Subject: [PATCH 11/15] Refactor: combine liveData into actionEvents, clean up log lines, and unneeded comments --- .../VoiceToContentActionEvent.kt | 4 ++ .../VoiceToContentDialogFragment.kt | 46 ++++++++----------- .../voicetocontent/VoiceToContentViewModel.kt | 30 +++++------- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt index 30b2c0353036..82473b1fa3f6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt @@ -3,5 +3,9 @@ package org.wordpress.android.ui.voicetocontent import org.wordpress.android.fluxc.model.SiteModel sealed class VoiceToContentActionEvent { + data object Dismiss: VoiceToContentActionEvent() data class LaunchEditPost(val site: SiteModel, val content: String) : VoiceToContentActionEvent() + data class LaunchExternalBrowser(val url: String) : VoiceToContentActionEvent() + data object RequestPermission : VoiceToContentActionEvent() + } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt index 9fba53c26c63..5807b5d34436 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt @@ -6,27 +6,30 @@ import android.content.DialogInterface import android.content.Intent import android.net.Uri import android.os.Bundle +import android.provider.Settings import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.FrameLayout import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog +import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.viewModels +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment import dagger.hilt.android.AndroidEntryPoint -import org.wordpress.android.ui.compose.theme.AppTheme import org.wordpress.android.R -import org.wordpress.android.util.audio.IAudioRecorder.Companion.REQUIRED_RECORDING_PERMISSIONS -import android.provider.Settings -import android.util.Log -import android.widget.FrameLayout -import androidx.compose.material.ExperimentalMaterialApi -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.bottomsheet.BottomSheetDialog import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.ActivityNavigator import org.wordpress.android.ui.PagePostCreationSourcesDetail +import org.wordpress.android.ui.compose.theme.AppTheme +import org.wordpress.android.ui.voicetocontent.VoiceToContentActionEvent.Dismiss +import org.wordpress.android.ui.voicetocontent.VoiceToContentActionEvent.LaunchEditPost +import org.wordpress.android.ui.voicetocontent.VoiceToContentActionEvent.LaunchExternalBrowser +import org.wordpress.android.ui.voicetocontent.VoiceToContentActionEvent.RequestPermission +import org.wordpress.android.util.audio.IAudioRecorder.Companion.REQUIRED_RECORDING_PERMISSIONS import javax.inject.Inject @AndroidEntryPoint @@ -80,17 +83,15 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { } override fun onSlide(bottomSheet: View, slideOffset: Float) { - // Handle the slide offset if needed } }) - // Disable touch interception by the bottom sheet to allow nested scrolling + // Disable touch interception by the bottom sheet to allow nested scrolling for landscape and small screens bottomSheet.setOnTouchListener { _, _ -> false } } // Observe the ViewModel to update the cancelable state of closing on outside touch viewModel.isCancelableOutsideTouch.observe(this) { cancelable -> - Log.i(javaClass.simpleName, "***=> disable outside touch") dialog.setCanceledOnTouchOutside(cancelable) } @@ -107,21 +108,12 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { } private fun observeViewModel() { - viewModel.requestPermission.observe(viewLifecycleOwner) { - requestAllPermissionsForRecording() - } - - viewModel.dismiss.observe(viewLifecycleOwner) { - dismiss() - } - - viewModel.onIneligibleForVoiceToContent.observe(viewLifecycleOwner) { url -> - launchIneligibleForVoiceToContent(url) - } - viewModel.actionEvent.observe(viewLifecycleOwner) { actionEvent -> when(actionEvent) { - is VoiceToContentActionEvent.LaunchEditPost -> launchEditPost(actionEvent) + is LaunchEditPost -> launchEditPost(actionEvent) + is LaunchExternalBrowser -> launchIneligibleForVoiceToContent(actionEvent) + is RequestPermission -> requestAllPermissionsForRecording() + is Dismiss -> dismiss() } } } @@ -159,13 +151,13 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { .show() } - private fun launchIneligibleForVoiceToContent(url: String) { + private fun launchIneligibleForVoiceToContent(event: LaunchExternalBrowser) { context?.let { - activityNavigator.openIneligibleForVoiceToContent(it, url) + activityNavigator.openIneligibleForVoiceToContent(it, event.url) } } - private fun launchEditPost(event: VoiceToContentActionEvent.LaunchEditPost) { + private fun launchEditPost(event: LaunchEditPost) { activity?.let { ActivityLauncher.addNewPostWithContentFromAIForResult( it, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index f879f6c704e3..ac3ddbb5a1cc 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -1,7 +1,6 @@ package org.wordpress.android.ui.voicetocontent import android.content.pm.PackageManager -import android.util.Log import androidx.core.content.ContextCompat import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData @@ -17,6 +16,10 @@ import org.wordpress.android.analytics.AnalyticsTracker.Stat import org.wordpress.android.fluxc.model.jetpackai.JetpackAIAssistantFeature import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.mysite.SelectedSiteRepository +import org.wordpress.android.ui.voicetocontent.VoiceToContentActionEvent.Dismiss +import org.wordpress.android.ui.voicetocontent.VoiceToContentActionEvent.LaunchEditPost +import org.wordpress.android.ui.voicetocontent.VoiceToContentActionEvent.LaunchExternalBrowser +import org.wordpress.android.ui.voicetocontent.VoiceToContentActionEvent.RequestPermission import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.ERROR import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.INELIGIBLE_FOR_FEATURE import org.wordpress.android.ui.voicetocontent.VoiceToContentUIStateType.INITIALIZING @@ -45,20 +48,11 @@ class VoiceToContentViewModel @Inject constructor( private val prepareVoiceToContentUseCase: PrepareVoiceToContentUseCase, private val logger: VoiceToContentTelemetry ) : ScopedViewModel(mainDispatcher) { - private val _requestPermission = MutableLiveData() - val requestPermission = _requestPermission as LiveData - - private val _dismiss = MutableLiveData() - val dismiss = _dismiss as LiveData - private val _recordingUpdate = MutableLiveData() - val recordingUpdate: LiveData get() = _recordingUpdate - - private val _onIneligibleForVoiceToContent = MutableLiveData() - val onIneligibleForVoiceToContent = _onIneligibleForVoiceToContent as LiveData + val recordingUpdate = _recordingUpdate as LiveData private val _isCancelableOutsideTouch = MutableLiveData(true) - val isCancelableOutsideTouch: LiveData get() = _isCancelableOutsideTouch + val isCancelableOutsideTouch = _isCancelableOutsideTouch as LiveData private val _actionEvent = MutableLiveData() val actionEvent = _actionEvent as LiveData @@ -127,8 +121,6 @@ class VoiceToContentViewModel @Inject constructor( stopRecording() } else { updateRecordingData(update) - // todo: Handle other updates if needed when UI is ready, e.g., elapsed time and file size - Log.d("AudioRecorder", "Recording update: $update") } } } @@ -185,16 +177,16 @@ class VoiceToContentViewModel @Inject constructor( when (val result = voiceToContentUseCase.execute(site, file)) { is VoiceToContentResult.Failure -> result.transitionToError() is VoiceToContentResult.Success -> - _actionEvent.postValue(VoiceToContentActionEvent.LaunchEditPost(site, result.content)) + _actionEvent.postValue(LaunchEditPost(site, result.content)) } - _dismiss.postValue(Unit) + _actionEvent.postValue(Dismiss) } } // Permissions private fun onRequestPermission() { logger.track(Stat.VOICE_TO_CONTENT_BUTTON_START_RECORDING_TAPPED) - _requestPermission.postValue(Unit) + _actionEvent.postValue(RequestPermission) } private fun hasAllPermissionsForRecording(): Boolean { @@ -224,7 +216,7 @@ class VoiceToContentViewModel @Inject constructor( private fun onClose() { logger.track(Stat.VOICE_TO_CONTENT_BUTTON_CLOSE_TAPPED) recordingUseCase.endRecordingSession() - _dismiss.postValue(Unit) + _actionEvent.postValue(Dismiss) } private fun onRetryTap() { @@ -235,7 +227,7 @@ class VoiceToContentViewModel @Inject constructor( private fun onLinkTap(url: String?) { logger.track(Stat.VOICE_TO_CONTENT_BUTTON_UPGRADE_TAPPED) url?.let { - _onIneligibleForVoiceToContent.postValue(it) + _actionEvent.postValue(LaunchExternalBrowser(it)) } } From 82c48d625e5da705290676e68394d4b038a38509 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:31:54 -0400 Subject: [PATCH 12/15] Address detekt issues --- .../android/ui/posts/EditPostActivity.kt | 19 +++++++------------ .../VoiceToContentDialogFragment.kt | 1 + 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt index 6973648afc02..e7c44262f0d9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt @@ -3534,18 +3534,13 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm } private fun updateVoiceContentIfNeeded() { - // Set the voiceToContent content if it exits and this is a GB Editor fragment - do this only once - val hasVoiceContent = intent.hasExtra(EditPostActivityConstants.EXTRA_VOICE_CONTENT) - if (isNewPost && hasVoiceContent && !isVoiceContentSet) { - editorFragment?.let { - if (it is GutenbergEditorFragment) { - val gutenbergFragment = editorFragment as GutenbergEditorFragment - val content = intent.getStringExtra(EditPostActivityConstants.EXTRA_VOICE_CONTENT) - content?.let { - isVoiceContentSet = true - gutenbergFragment.updateContent(content) - } - } + // Check if voice content exists and this is a new post for a Gutenberg editor fragment + val content = intent.getStringExtra(EditPostActivityConstants.EXTRA_VOICE_CONTENT) + if (isNewPost && content != null && !isVoiceContentSet) { + val gutenbergFragment = editorFragment as? GutenbergEditorFragment + gutenbergFragment?.let { + isVoiceContentSet = true + it.updateContent(content) } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt index 5807b5d34436..c32a850d0145 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentDialogFragment.kt @@ -83,6 +83,7 @@ class VoiceToContentDialogFragment : BottomSheetDialogFragment() { } override fun onSlide(bottomSheet: View, slideOffset: Float) { + // no op } }) From 5a648b3873b135967cdd50db26b0623cb52b48b9 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Sat, 15 Jun 2024 11:33:24 -0400 Subject: [PATCH 13/15] Address checkstlye be removing empty line --- .../android/ui/voicetocontent/VoiceToContentActionEvent.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt index 82473b1fa3f6..543a95b8ed53 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentActionEvent.kt @@ -7,5 +7,4 @@ sealed class VoiceToContentActionEvent { data class LaunchEditPost(val site: SiteModel, val content: String) : VoiceToContentActionEvent() data class LaunchExternalBrowser(val url: String) : VoiceToContentActionEvent() data object RequestPermission : VoiceToContentActionEvent() - } From 2758f22519d8a0bac2bcdf4c842a9d059256c0be Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Tue, 18 Jun 2024 09:02:59 -0400 Subject: [PATCH 14/15] Remove errant dismiss call --- .../android/ui/voicetocontent/VoiceToContentViewModel.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt index ac3ddbb5a1cc..088ab86fa345 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/voicetocontent/VoiceToContentViewModel.kt @@ -179,7 +179,6 @@ class VoiceToContentViewModel @Inject constructor( is VoiceToContentResult.Success -> _actionEvent.postValue(LaunchEditPost(site, result.content)) } - _actionEvent.postValue(Dismiss) } } From 82a6ca668a10a96036538c15cabfba43d8769a30 Mon Sep 17 00:00:00 2001 From: Annmarie Ziegler Date: Wed, 19 Jun 2024 07:33:14 -0400 Subject: [PATCH 15/15] Fix using the wrong state key --- .../java/org/wordpress/android/ui/posts/EditPostActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt index e7c44262f0d9..caf240ccdb63 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/EditPostActivity.kt @@ -718,7 +718,7 @@ class EditPostActivity : LocaleAwareActivity(), EditorFragmentActivity, EditorIm } isNewPost = state.getBoolean(EditPostActivityConstants.STATE_KEY_IS_NEW_POST, false) - isVoiceContentSet = state.getBoolean(EditPostActivityConstants.STATE_KEY_IS_NEW_POST, false) + isVoiceContentSet = state.getBoolean(EditPostActivityConstants.STATE_KEY_IS_VOICE_CONTENT_SET, false) updatePostLoadingAndDialogState( fromInt( state.getInt(EditPostActivityConstants.STATE_KEY_POST_LOADING_STATE, 0)