diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/InviteFriendFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/InviteFriendFragment.kt new file mode 100644 index 0000000000..952bc0dba5 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/InviteFriendFragment.kt @@ -0,0 +1,115 @@ +package org.thoughtcrime.securesms.conversation.start + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.fragment.app.Fragment +import dagger.hilt.android.AndroidEntryPoint +import network.loki.messenger.R +import org.session.libsession.utilities.TextSecurePreferences +import org.thoughtcrime.securesms.preferences.copyPublicKey +import org.thoughtcrime.securesms.preferences.sendInvitation +import org.thoughtcrime.securesms.ui.AppTheme +import org.thoughtcrime.securesms.ui.classicDarkColors +import org.thoughtcrime.securesms.ui.components.AppBar +import org.thoughtcrime.securesms.ui.components.OnPrimaryButtons +import org.thoughtcrime.securesms.ui.components.OutlineButton +import org.thoughtcrime.securesms.ui.components.SmallButtons +import org.thoughtcrime.securesms.ui.components.TemporaryStateButton + +@AndroidEntryPoint +class InviteFriendFragment : Fragment() { + lateinit var delegate: NewConversationDelegate + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View = ComposeView(requireContext()).apply { + setContent { + AppTheme { + InviteFriend() + } + } + } + + @Composable + private fun InviteFriend() { + Column(modifier = Modifier.background(MaterialTheme.colors.surface)) { + AppBar("Invite a Friend", onBack = { delegate.onDialogBackPressed() }, onClose = { delegate.onDialogClosePressed() }) + Column( + modifier = Modifier.padding(horizontal = 24.dp), + verticalArrangement = spacedBy(10.dp) + ) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = classicDarkColors[5], + shape = RoundedCornerShape(size = 13.dp) + ) + .fillMaxWidth() + .wrapContentHeight() + ) { + Text( + TextSecurePreferences.getLocalNumber(LocalContext.current)!!, + textAlign = TextAlign.Center, + modifier = Modifier + .align(Alignment.Center) + .padding(22.dp) + ) + } + + Text( + "Invite your friend to chat with you on Session by sharing your Account ID with them.", + textAlign = TextAlign.Center, + modifier = Modifier.padding(horizontal = 8.dp) + ) + OnPrimaryButtons { + SmallButtons { + Row(horizontalArrangement = spacedBy(20.dp)) { + OutlineButton( + modifier = Modifier.weight(1f), + onClick = { requireContext().sendInvitation() } + ) { + Text(stringResource(R.string.share)) + } + + TemporaryStateButton { source, temporary -> + OutlineButton( + modifier = Modifier.weight(1f), + interactionSource = source, + onClick = { requireContext().copyPublicKey() }, + ) { + AnimatedVisibility(temporary) { Text(stringResource(R.string.copied)) } + AnimatedVisibility(!temporary) { Text(stringResource(R.string.copy)) } + } + } + } + } + } + } + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationFragment.kt index 33d58ee89f..25292078c8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationFragment.kt @@ -35,7 +35,7 @@ class NewConversationFragment : BottomSheetDialogFragment(), NewConversationDele override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) replaceFragment( - fragment = NewConversationHomeFragment().apply { delegate = this@NewConversationFragment }, + fragment = NewConversationHomeFragment().also { it.delegate = this }, fragmentKey = NewConversationHomeFragment::class.java.simpleName ) } @@ -44,8 +44,7 @@ class NewConversationFragment : BottomSheetDialogFragment(), NewConversationDele val dialog = BottomSheetDialog(requireContext(), R.style.Theme_Session_BottomSheet) dialog.setOnShowListener { val bottomSheetDialog = it as BottomSheetDialog - val parentLayout = - bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet) + val parentLayout = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet) parentLayout?.let { val behaviour = BottomSheetBehavior.from(it) val layoutParams = it.layoutParams @@ -58,15 +57,15 @@ class NewConversationFragment : BottomSheetDialogFragment(), NewConversationDele } override fun onNewMessageSelected() { - replaceFragment(NewMessageFragment().apply { delegate = this@NewConversationFragment }) + replaceFragment(NewMessageFragment().also { it.delegate = this }) } override fun onCreateGroupSelected() { - replaceFragment(CreateGroupFragment().apply { delegate = this@NewConversationFragment }) + replaceFragment(CreateGroupFragment().also { it.delegate = this }) } override fun onJoinCommunitySelected() { - replaceFragment(JoinCommunityFragment().apply { delegate = this@NewConversationFragment }) + replaceFragment(JoinCommunityFragment().also { it.delegate = this }) } override fun onContactSelected(address: String) { @@ -81,7 +80,7 @@ class NewConversationFragment : BottomSheetDialogFragment(), NewConversationDele } override fun onInviteFriend() { - + replaceFragment(InviteFriendFragment().also { it.delegate = this }) } override fun onDialogClosePressed() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt index c0d0b49047..02c8de55b0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height @@ -51,7 +52,7 @@ class NewConversationHomeFragment : Fragment() { @Composable fun NewConversationScreen() { - Column { + Column(modifier = Modifier.background(MaterialTheme.colors.surface)) { AppBar(stringResource(R.string.dialog_new_conversation_title), onClose = { delegate.onDialogClosePressed() }) ItemButton(textId = R.string.messageNew, icon = R.drawable.ic_message) { delegate.onNewMessageSelected() } Divider(modifier = Modifier.padding(start = 80.dp)) diff --git a/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt index 78364532e4..b21920c560 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt @@ -30,6 +30,8 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.launch import network.loki.messenger.R import org.session.libsession.utilities.Address @@ -61,10 +63,8 @@ class NewMessageFragment : Fragment() { super.onCreate(savedInstanceState) lifecycleScope.launch { - viewModel.event.collect { - when (it) { - is Event.Success -> createPrivateChat(it.key) - } + viewModel.event.filterIsInstance().collect { + createPrivateChat(it.key) } } } @@ -121,7 +121,7 @@ private fun NewMessage( ) { val pagerState = rememberPagerState { TITLES.size } - Column(modifier = Modifier.background(MaterialTheme.colors.background)) { + Column(modifier = Modifier.background(MaterialTheme.colors.surface)) { AppBar(stringResource(R.string.messageNew), onClose = { onClose() }, onBack = { onBack() }) SessionTabRow(pagerState, TITLES) HorizontalPager(pagerState) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt index 2cca42386e..ccd6a60fbb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt @@ -42,6 +42,7 @@ import org.thoughtcrime.securesms.ui.SessionShieldIcon import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider import org.thoughtcrime.securesms.ui.classicDarkColors import org.thoughtcrime.securesms.ui.colorDestructive +import org.thoughtcrime.securesms.ui.components.DestructiveButtons import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.components.QrImage import org.thoughtcrime.securesms.ui.components.SmallButtons @@ -205,9 +206,7 @@ fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) { Text(text = stringResource(R.string.recoveryPasswordHideRecoveryPassword), style = MaterialTheme.typography.h8) Text(text = stringResource(R.string.recoveryPasswordHideRecoveryPasswordDescription)) } - CompositionLocalProvider( - LocalButtonColor provides colorDestructive, - ) { + DestructiveButtons { OutlineButton( textId = R.string.hide, modifier = Modifier diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt index a0d96da0e8..9c08898f33 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt @@ -3,8 +3,6 @@ package org.thoughtcrime.securesms.preferences import android.Manifest import android.app.Activity import android.content.BroadcastReceiver -import android.content.ClipData -import android.content.ClipboardManager import android.content.Context import android.content.Intent import android.content.IntentFilter @@ -353,32 +351,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { } .execute() } - - private fun copyPublicKey() { - val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText("Session ID", hexEncodedPublicKey) - clipboard.setPrimaryClip(clip) - Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show() - } - - private fun sharePublicKey() { - Intent().apply { - action = Intent.ACTION_SEND - putExtra(Intent.EXTRA_TEXT, hexEncodedPublicKey) - type = "text/plain" - }.let { Intent.createChooser(it, getString(R.string.share)) } - .let(::startActivity) - } - - private fun sendInvitation() { - Intent().apply { - action = Intent.ACTION_SEND - putExtra(Intent.EXTRA_TEXT, "Hey, I've been using Session to chat with complete privacy and security. Come join me! Download it at https://getsession.org/. My Session ID is $hexEncodedPublicKey !") - type = "text/plain" - }.let { Intent.createChooser(it, getString(R.string.activity_settings_invite_button_title)) } - .let(::startActivity) - } - // endregion private inner class DisplayNameEditActionModeCallback: ActionMode.Callback { @@ -420,7 +392,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { ) { OutlineButton( modifier = Modifier.weight(1f), - onClick = ::sharePublicKey + onClick = { sendInvitation() } ) { Text(stringResource(R.string.share)) } @@ -499,4 +471,4 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { fun createReceiver(update: () -> Unit) = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { update() } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/Util.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/Util.kt new file mode 100644 index 0000000000..80bed35992 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/Util.kt @@ -0,0 +1,32 @@ +package org.thoughtcrime.securesms.preferences + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Intent +import android.widget.Toast +import network.loki.messenger.R +import org.session.libsession.utilities.TextSecurePreferences + +fun Context.sendInvitation() { + Intent().apply { + action = Intent.ACTION_SEND + putExtra( + Intent.EXTRA_TEXT, + """Hey, I've been using Session to chat with complete privacy and security. Come join me! My Account ID is + +${TextSecurePreferences.getLocalNumber(this@sendInvitation)} + +Download it at https://getsession.org/""" + ) + type = "text/plain" + }.let { Intent.createChooser(it, getString(R.string.activity_settings_invite_button_title)) } + .let(::startActivity) +} + +fun Context.copyPublicKey() { + val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("Session ID", TextSecurePreferences.getLocalNumber(this)) + clipboard.setPrimaryClip(clip) + Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show() +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt index 2906b882d3..ff0d88d528 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt @@ -80,6 +80,7 @@ import org.session.libsession.utilities.recipients.Recipient import org.session.libsession.utilities.runIf import org.thoughtcrime.securesms.components.ProfilePictureView import org.thoughtcrime.securesms.conversation.disappearingmessages.ui.OptionsCard +import org.thoughtcrime.securesms.ui.components.OnPrimaryButtons import kotlin.math.min import kotlin.math.roundToInt @@ -219,7 +220,7 @@ fun CellWithPaddingAndMargin( margin: Dp = 32.dp, content: @Composable () -> Unit ) { - CompositionLocalProvider(LocalButtonColor provides MaterialTheme.colors.onPrimary) { + OnPrimaryButtons { Card( backgroundColor = LocalCellColor.current, shape = RoundedCornerShape(16.dp), diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt index ec54846b19..7b16130a9f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt @@ -172,3 +172,8 @@ fun SmallButtons(content: @Composable () -> Unit) { fun DestructiveButtons(content: @Composable () -> Unit) { CompositionLocalProvider(LocalButtonColor provides colorDestructive) { content() } } + +@Composable +fun OnPrimaryButtons(content: @Composable () -> Unit) { + CompositionLocalProvider(LocalButtonColor provides MaterialTheme.colors.onPrimary) { content() } +}