From 28d92fd547c8fa2fc50e18393d3afb4b8e0ae671 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 17 Oct 2023 18:18:53 +1030 Subject: [PATCH] Update MessageNotificationsActivity --- app/src/main/AndroidManifest.xml | 2 +- .../securesms/onboarding/LoadingActivity.kt | 1 + .../securesms/onboarding/PNModeActivity.kt | 187 ------------------ .../MessageNotificationsActivity.kt | 156 +++++++++++++++ .../MessageNotificationsViewModel.kt | 22 +++ .../pickname/PickDisplayNameActivity.kt | 4 +- .../res/layout-sw400dp/activity_pn_mode.xml | 119 ----------- app/src/main/res/layout/activity_pn_mode.xml | 118 ----------- app/src/main/res/menu/menu_pn_mode.xml | 11 -- 9 files changed, 181 insertions(+), 439 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/onboarding/PNModeActivity.kt create mode 100644 app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt create mode 100644 app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt delete mode 100644 app/src/main/res/layout-sw400dp/activity_pn_mode.xml delete mode 100644 app/src/main/res/layout/activity_pn_mode.xml delete mode 100644 app/src/main/res/menu/menu_pn_mode.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 54b888489..bd9774783 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -120,7 +120,7 @@ android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.Session.DayNight.FlatActionBar" /> learnMore() - else -> { /* Do nothing */ } - } - return super.onOptionsItemSelected(item) - } - - private fun learnMore() { - try { - val url = "https://getsession.org/faq/#privacy" - val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) - startActivity(intent) - } catch (e: Exception) { - Toast.makeText(this, R.string.invalid_url, Toast.LENGTH_SHORT).show() - } - } - - private fun toggleFCM() = with(binding) { - val accentColor = getAccentColor() - when (selectedOptionView) { - null -> { - performTransition(R.drawable.pn_option_background_select_transition, fcmOptionView) - GlowViewUtilities.animateShadowColorChange(fcmOptionView, resources.getColorWithID(R.color.transparent, theme), accentColor) - animateStrokeColorChange(fcmOptionView, resources.getColorWithID(R.color.pn_option_border, theme), accentColor) - selectedOptionView = fcmOptionView - } - fcmOptionView -> { - performTransition(R.drawable.pn_option_background_deselect_transition, fcmOptionView) - GlowViewUtilities.animateShadowColorChange(fcmOptionView, accentColor, resources.getColorWithID(R.color.transparent, theme)) - animateStrokeColorChange(fcmOptionView, accentColor, resources.getColorWithID(R.color.pn_option_border, theme)) - selectedOptionView = null - } - backgroundPollingOptionView -> { - performTransition(R.drawable.pn_option_background_select_transition, fcmOptionView) - GlowViewUtilities.animateShadowColorChange(fcmOptionView, resources.getColorWithID(R.color.transparent, theme), accentColor) - animateStrokeColorChange(fcmOptionView, resources.getColorWithID(R.color.pn_option_border, theme), accentColor) - performTransition(R.drawable.pn_option_background_deselect_transition, backgroundPollingOptionView) - GlowViewUtilities.animateShadowColorChange(backgroundPollingOptionView, accentColor, resources.getColorWithID(R.color.transparent, theme)) - animateStrokeColorChange(backgroundPollingOptionView, accentColor, resources.getColorWithID(R.color.pn_option_border, theme)) - selectedOptionView = fcmOptionView - } - } - } - - private fun toggleBackgroundPolling() = with(binding) { - val accentColor = getAccentColor() - when (selectedOptionView) { - null -> { - performTransition(R.drawable.pn_option_background_select_transition, backgroundPollingOptionView) - GlowViewUtilities.animateShadowColorChange(backgroundPollingOptionView, resources.getColorWithID(R.color.transparent, theme), accentColor) - animateStrokeColorChange(backgroundPollingOptionView, resources.getColorWithID(R.color.pn_option_border, theme), accentColor) - selectedOptionView = backgroundPollingOptionView - } - backgroundPollingOptionView -> { - performTransition(R.drawable.pn_option_background_deselect_transition, backgroundPollingOptionView) - GlowViewUtilities.animateShadowColorChange(backgroundPollingOptionView, accentColor, resources.getColorWithID(R.color.transparent, theme)) - animateStrokeColorChange(backgroundPollingOptionView, accentColor, resources.getColorWithID(R.color.pn_option_border, theme)) - selectedOptionView = null - } - fcmOptionView -> { - performTransition(R.drawable.pn_option_background_select_transition, backgroundPollingOptionView) - GlowViewUtilities.animateShadowColorChange(backgroundPollingOptionView, resources.getColorWithID(R.color.transparent, theme), accentColor) - animateStrokeColorChange(backgroundPollingOptionView, resources.getColorWithID(R.color.pn_option_border, theme), accentColor) - performTransition(R.drawable.pn_option_background_deselect_transition, fcmOptionView) - GlowViewUtilities.animateShadowColorChange(fcmOptionView, accentColor, resources.getColorWithID(R.color.transparent, theme)) - animateStrokeColorChange(fcmOptionView, accentColor, resources.getColorWithID(R.color.pn_option_border, theme)) - selectedOptionView = backgroundPollingOptionView - } - } - } - - private fun animateStrokeColorChange(bubble: PNModeView, @ColorInt startColor: Int, @ColorInt endColor: Int) { - val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor) - animation.duration = 250 - animation.addUpdateListener { animator -> - val color = animator.animatedValue as Int - bubble.strokeColor = color - } - animation.start() - } - - private fun register() { - if (selectedOptionView == null) { - showSessionDialog { - title(R.string.activity_pn_mode_no_option_picked_dialog_title) - button(R.string.ok) - } - return - } - - TextSecurePreferences.setPushEnabled(this, (selectedOptionView == binding.fcmOptionView)) - val application = ApplicationContext.getInstance(this) - application.startPollingIfNeeded() - pushRegistry.refresh(true) - val intent = Intent(this, HomeActivity::class.java) - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK - intent.putExtra(HomeActivity.FROM_ONBOARDING, true) - show(intent) - } - // endregion -} - -fun Context.startPNModeActivity(flags: Int = 0) { - Intent(this, PNModeActivity::class.java) - .also { it.flags = flags } - .also(::startActivity) -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt new file mode 100644 index 000000000..a0eab206e --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt @@ -0,0 +1,156 @@ +package org.thoughtcrime.securesms.onboarding.messagenotifications + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.activity.viewModels +import androidx.annotation.StringRes +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.MaterialTheme +import androidx.compose.material.OutlinedButton +import androidx.compose.material.RadioButton +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import dagger.hilt.android.AndroidEntryPoint +import network.loki.messenger.R +import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.ApplicationContext +import org.thoughtcrime.securesms.BaseActionBarActivity +import org.thoughtcrime.securesms.home.HomeActivity +import org.thoughtcrime.securesms.notifications.PushRegistry +import org.thoughtcrime.securesms.ui.AppTheme +import org.thoughtcrime.securesms.ui.OutlineButton +import org.thoughtcrime.securesms.ui.h8 +import org.thoughtcrime.securesms.ui.h9 +import org.thoughtcrime.securesms.ui.session_accent +import org.thoughtcrime.securesms.ui.small +import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo +import javax.inject.Inject + +@AndroidEntryPoint +class MessageNotificationsActivity : BaseActionBarActivity() { + + @Inject lateinit var pushRegistry: PushRegistry + + private val viewModel: MessageNotificationsViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setUpActionBarSessionLogo(true) + TextSecurePreferences.setHasSeenWelcomeScreen(this, true) + + ComposeView(this) + .apply { setContent { MessageNotifications() } } + .let(::setContentView) + } + + @Composable + private fun MessageNotifications() { + val state by viewModel.stateFlow.collectAsState() + + MessageNotifications(state, viewModel::setEnabled, ::register) + } + + private fun register() { + TextSecurePreferences.setPushEnabled(this, viewModel.stateFlow.value.pushEnabled) + ApplicationContext.getInstance(this).startPollingIfNeeded() + pushRegistry.refresh(true) + Intent(this, HomeActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + putExtra(HomeActivity.FROM_ONBOARDING, true) + }.also(::startActivity) + } +} + +@Preview +@Composable +fun MessageNotifications( + state: MessageNotificationsState = MessageNotificationsState(), + setEnabled: (Boolean) -> Unit = {}, + onContinue: () -> Unit = {} +) { + AppTheme { + Column(Modifier.padding(horizontal = 32.dp)) { + Spacer(Modifier.weight(1f)) + Text("Message notifications", style = MaterialTheme.typography.h4) + Spacer(Modifier.height(16.dp)) + Text("There are two ways Session can notify you of new messages.") + Spacer(Modifier.height(16.dp)) + NotificationRadioButton( + R.string.activity_pn_mode_fast_mode, + R.string.activity_pn_mode_fast_mode_explanation, + R.string.activity_pn_mode_recommended_option_tag, + selected = state.pushEnabled, + onClick = { setEnabled(true) } + ) + Spacer(Modifier.height(16.dp)) + NotificationRadioButton( + R.string.activity_pn_mode_slow_mode, + R.string.activity_pn_mode_slow_mode_explanation, + selected = state.pushDisabled, + onClick = { setEnabled(false) } + ) + Spacer(Modifier.weight(1f)) + OutlineButton( + stringResource(R.string.continue_2), + modifier = Modifier + .align(Alignment.CenterHorizontally) + .width(262.dp), + onClick = onContinue + ) + Spacer(modifier = Modifier.height(12.dp)) + } + } +} + +@Composable +fun NotificationRadioButton( + @StringRes title: Int, + @StringRes explanation: Int, + @StringRes tag: Int? = null, + selected: Boolean = false, + onClick: () -> Unit = {} +) { + Row { + OutlinedButton( + onClick = onClick, + modifier = Modifier.weight(1f), + colors = ButtonDefaults.outlinedButtonColors(backgroundColor = MaterialTheme.colors.background, contentColor = Color.White), + border = if (selected) BorderStroke(ButtonDefaults.OutlinedBorderSize, session_accent) else ButtonDefaults.outlinedBorder, + shape = RoundedCornerShape(8.dp) + ) { + Column( + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text(stringResource(title), style = MaterialTheme.typography.h8) + Text(stringResource(explanation), style = MaterialTheme.typography.small) + tag?.let { Text(stringResource(it), color = session_accent, style = MaterialTheme.typography.h9) } + } + } + RadioButton(selected = selected, modifier = Modifier.align(Alignment.CenterVertically), onClick = onClick) + } +} + +fun Context.startPNModeActivity(flags: Int = 0) { + Intent(this, MessageNotificationsActivity::class.java) + .also { it.flags = flags } + .also(::startActivity) +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt new file mode 100644 index 000000000..f913e0444 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt @@ -0,0 +1,22 @@ +package org.thoughtcrime.securesms.onboarding.messagenotifications + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import javax.inject.Inject + +@HiltViewModel +class MessageNotificationsViewModel @Inject constructor(): ViewModel() { + private val state = MutableStateFlow(MessageNotificationsState()) + val stateFlow = state.asStateFlow() + + fun setEnabled(enabled: Boolean) { + state.update { MessageNotificationsState(pushEnabled = enabled) } + } +} + +data class MessageNotificationsState(val pushEnabled: Boolean = true) { + val pushDisabled get() = !pushEnabled +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt index 44f913f2d..729194a5d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt @@ -32,9 +32,7 @@ import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch import network.loki.messenger.R import org.thoughtcrime.securesms.BaseActionBarActivity -import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2 -import org.thoughtcrime.securesms.conversation.v2.ConversationViewModel -import org.thoughtcrime.securesms.onboarding.startPNModeActivity +import org.thoughtcrime.securesms.onboarding.messagenotifications.startPNModeActivity import org.thoughtcrime.securesms.ui.AppTheme import org.thoughtcrime.securesms.ui.OutlineButton import org.thoughtcrime.securesms.ui.PreviewTheme diff --git a/app/src/main/res/layout-sw400dp/activity_pn_mode.xml b/app/src/main/res/layout-sw400dp/activity_pn_mode.xml deleted file mode 100644 index b55b35f14..000000000 --- a/app/src/main/res/layout-sw400dp/activity_pn_mode.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - -