Introduce conversation settings screen

This commit is contained in:
Sebastian Kürten
2021-01-21 19:21:10 +01:00
committed by Torsten Grote
parent 5ae2a37d37
commit 8510fc80c9
10 changed files with 296 additions and 14 deletions

View File

@@ -27,6 +27,7 @@ import org.briarproject.briar.android.contact.add.remote.NicknameFragment;
import org.briarproject.briar.android.contact.add.remote.PendingContactListActivity;
import org.briarproject.briar.android.conversation.AliasDialogFragment;
import org.briarproject.briar.android.conversation.ConversationActivity;
import org.briarproject.briar.android.conversation.ConversationSettingsDialog;
import org.briarproject.briar.android.conversation.ImageActivity;
import org.briarproject.briar.android.conversation.ImageFragment;
import org.briarproject.briar.android.forum.CreateForumActivity;
@@ -238,4 +239,6 @@ public interface ActivityComponent {
void inject(ConfirmAvatarDialogFragment fragment);
void inject(ConversationSettingsDialog dialog);
}

View File

@@ -31,6 +31,8 @@ import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
// TODO: we can probably switch to androidx DialogFragment here but need to
// test this properly
public class AliasDialogFragment extends AppCompatDialogFragment {
final static String TAG = AliasDialogFragment.class.getName();

View File

@@ -50,6 +50,7 @@ import org.briarproject.briar.android.blog.BlogActivity;
import org.briarproject.briar.android.conversation.ConversationVisitor.AttachmentCache;
import org.briarproject.briar.android.conversation.ConversationVisitor.TextCache;
import org.briarproject.briar.android.forum.ForumActivity;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.android.introduction.IntroductionActivity;
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
@@ -136,7 +137,6 @@ import static org.briarproject.briar.android.conversation.ImageActivity.ITEM_ID;
import static org.briarproject.briar.android.conversation.ImageActivity.NAME;
import static org.briarproject.briar.android.util.UiUtils.observeOnce;
import static org.briarproject.briar.android.view.AuthorView.setAvatar;
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_ATTACHMENTS_PER_MESSAGE;
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_TEXT_LENGTH;
import static org.briarproject.briar.api.messaging.PrivateMessageFormat.TEXT_IMAGES_AUTO_DELETE;
@@ -145,8 +145,8 @@ import static org.briarproject.briar.api.messaging.PrivateMessageFormat.TEXT_ONL
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ConversationActivity extends BriarActivity
implements EventListener, ConversationListener, TextCache,
AttachmentCache, AttachmentListener, ActionMode.Callback {
implements BaseFragmentListener, EventListener, ConversationListener,
TextCache, AttachmentCache, AttachmentListener, ActionMode.Callback {
public static final String CONTACT_ID = "briar.CONTACT_ID";
@@ -374,10 +374,8 @@ public class ConversationActivity extends BriarActivity
// show auto-delete timer setting only, if contacts supports it
observeOnce(viewModel.getPrivateMessageFormat(), this, format -> {
boolean visible = format == TEXT_IMAGES_AUTO_DELETE;
MenuItem item = menu.findItem(R.id.action_auto_delete);
MenuItem item = menu.findItem(R.id.action_conversation_settings);
item.setVisible(visible);
viewModel.getAutoDeleteTimer().observe(this, timer ->
item.setChecked(timer != NO_AUTO_DELETE_TIMER));
});
return super.onCreateOptionsMenu(menu);
@@ -400,10 +398,12 @@ public class ConversationActivity extends BriarActivity
AliasDialogFragment.newInstance().show(
getSupportFragmentManager(), AliasDialogFragment.TAG);
return true;
case R.id.action_auto_delete:
boolean enabled = !item.isChecked();
viewModel.setAutoDeleteTimerEnabled(enabled);
item.setChecked(enabled);
case R.id.action_conversation_settings:
if (contactId == null) return false;
ConversationSettingsDialog dialog =
ConversationSettingsDialog.newInstance(contactId);
dialog.show(getSupportFragmentManager(),
ConversationSettingsDialog.TAG);
return true;
case R.id.action_delete_all_messages:
askToDeleteAllMessages();

View File

@@ -0,0 +1,122 @@
package org.briarproject.briar.android.conversation;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import java.util.logging.Logger;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ConversationSettingsDialog extends DialogFragment {
final static String TAG = ConversationSettingsDialog.class.getName();
private static final Logger LOG = Logger.getLogger(TAG);
@Inject
ViewModelProvider.Factory viewModelFactory;
private ConversationViewModel viewModel;
static ConversationSettingsDialog newInstance(ContactId contactId) {
Bundle args = new Bundle();
args.putInt(CONTACT_ID, contactId.getInt());
ConversationSettingsDialog dialog = new ConversationSettingsDialog();
dialog.setArguments(args);
return dialog;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
injectFragment(((BaseFragment.BaseFragmentListener) context)
.getActivityComponent());
}
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(ConversationViewModel.class);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_FRAME,
R.style.BriarFullScreenDialogTheme);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_conversation_settings,
container, false);
Bundle args = requireArguments();
int id = args.getInt(CONTACT_ID, -1);
if (id == -1) throw new IllegalStateException();
ContactId contactId = new ContactId(id);
FragmentActivity activity = requireActivity();
viewModel = new ViewModelProvider(activity, viewModelFactory)
.get(ConversationViewModel.class);
viewModel.setContactId(contactId);
Toolbar toolbar = view.findViewById(R.id.toolbar);
toolbar.setNavigationOnClickListener(v -> dismiss());
SwitchCompat switchDisappearingMessages = view.findViewById(
R.id.switchDisappearingMessages);
switchDisappearingMessages.setOnCheckedChangeListener(
(button, value) -> viewModel.setAutoDeleteTimerEnabled(value));
TextView buttonLearnMore =
view.findViewById(R.id.buttonLearnMore);
buttonLearnMore.setOnClickListener(e -> showLearnMoreDialog());
viewModel.getAutoDeleteTimer()
.observe(getViewLifecycleOwner(), timer -> {
LOG.info("Received auto delete timer: " + timer);
boolean disappearingMessages =
timer != NO_AUTO_DELETE_TIMER;
switchDisappearingMessages
.setChecked(disappearingMessages);
switchDisappearingMessages.setEnabled(true);
});
return view;
}
private void showLearnMoreDialog() {
ConversationSettingsLearnMoreDialog
dialog = new ConversationSettingsLearnMoreDialog();
dialog.show(getChildFragmentManager(),
ConversationSettingsLearnMoreDialog.TAG);
}
}

View File

@@ -0,0 +1,43 @@
package org.briarproject.briar.android.conversation;
import android.app.Dialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ConversationSettingsLearnMoreDialog extends DialogFragment {
final static String TAG =
ConversationSettingsLearnMoreDialog.class.getName();
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
FragmentActivity activity = requireActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(activity,
R.style.OnboardingDialogTheme);
LayoutInflater inflater = LayoutInflater.from(builder.getContext());
View view = inflater.inflate(
R.layout.fragment_conversation_settings_learn_more, null);
builder.setView(view);
builder.setTitle(R.string.disappearing_messages_title);
builder.setPositiveButton(R.string.ok, null);
return builder.create();
}
}

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
style="@style/BriarToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/abc_ic_ab_back_material"
app:title="@string/disappearing_messages_title" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingHorizontal="@dimen/margin_large"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageViewBomb"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_bomb"
app:tint="?attr/colorControlNormal"
tools:ignore="ContentDescription" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switchDisappearingMessages"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:enabled="false"
android:text="@string/disappearing_messages_summary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageViewBomb" />
<TextView
android:id="@+id/buttonLearnMore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_large"
android:clickable="true"
android:focusable="true"
android:text="@string/learn_more"
android:textColor="@color/briar_text_link"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/switchDisappearingMessages" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="?dialogPreferredPadding">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/disappearing_messages_explanation_long"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ScrollView>

View File

@@ -17,9 +17,8 @@
app:showAsAction="never" />
<item
android:id="@+id/action_auto_delete"
android:checkable="true"
android:title="@string/menu_item_auto_delete"
android:id="@+id/action_conversation_settings"
android:title="@string/menu_item_disappearing_messages"
android:visible="false"
app:showAsAction="never"
tools:visible="true" />

View File

@@ -166,7 +166,7 @@
<string name="image_attach_error_invalid_mime_type">Image format unsupported: %s</string>
<string name="set_contact_alias">Change contact name</string>
<string name="set_contact_alias_hint">Contact name</string>
<string name="menu_item_auto_delete">Disappearing messages</string>
<string name="menu_item_disappearing_messages">Disappearing messages</string>
<string name="auto_delete_msg_you_enabled">Your messages will disappear after 7 days.</string>
<string name="auto_delete_msg_you_disabled">Your messages will not disappear.</string>
<string name="auto_delete_msg_contact_enabled">%1$s\'s messages will disappear after 7 days.</string>
@@ -557,6 +557,19 @@
<string name="choose_ringtone_title">Choose ringtone</string>
<string name="cannot_load_ringtone">Cannot load ringtone</string>
<!-- Conversation Settings -->
<string name="disappearing_messages_title">Disappearing messages</string>
<string name="disappearing_messages_explanation_long">Turning on this setting will make new
messages in this conversation automatically disappear 7\u00A0days after being received.
This applies to messages you send to your contact as well as messages your contact sends to you.
Your contact can also change this setting for the both of you.
\n\nMessages that will disappear are marked with a bomb icon.
\n\nKeep in mind that recipients can still make copies of the messages you send.
\n\nIf you change this setting, it will apply to your messages immediately and to your
contact\'s messages once they receive your next message.</string>
<string name="learn_more">Learn more</string>
<string name="disappearing_messages_summary">Make future messages in this conversation automatically disappear 7\u00A0days after being received.</string>
<!-- Settings Feedback -->
<string name="feedback_settings_title">Feedback</string>
<string name="send_feedback">Send feedback</string>

View File

@@ -43,6 +43,16 @@
<item name="android:filterTouchesWhenObscured">true</item>
</style>
<style name="BriarFullScreenDialogTheme" parent="BriarDialogTheme">
<item name="android:windowIsFloating">false</item>
<item name="android:windowAnimationStyle">@style/FullScreenDialogAnimation</item>
</style>
<style name="FullScreenDialogAnimation" parent="@android:style/Animation.Activity">
<item name="android:windowEnterAnimation">@anim/step_next_in</item>
<item name="android:windowExitAnimation">@anim/step_next_out</item>
</style>
<!-- Use this with care. Only used for the screen filter warning dialog -->
<style name="BriarDialogThemeNoFilter" parent="BriarDialogTheme">
<item name="android:filterTouchesWhenObscured">false</item>