Add mute/unmute messages and mentions

This commit is contained in:
Ammar Githam 2021-01-17 17:02:43 +09:00
parent 13d95523a3
commit 52d2baa128
6 changed files with 248 additions and 29 deletions

View File

@ -7,6 +7,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -176,6 +177,7 @@ public class DirectMessageSettingsFragment extends Fragment {
if (usersAdapter == null) return;
usersAdapter.setAdminUserIds(adminUserIds);
});
viewModel.getMuted().observe(getViewLifecycleOwner(), muted -> binding.muteMessages.setChecked(muted));
final NavController navController = NavHostFragment.findNavController(this);
final NavBackStackEntry backStackEntry = navController.getCurrentBackStackEntry();
if (backStackEntry != null) {
@ -202,7 +204,7 @@ public class DirectMessageSettingsFragment extends Fragment {
detailsChangeResourceLiveData = viewModel.addMembers(users);
} catch (Exception e) {
Log.e(TAG, "search users result: ", e);
Snackbar.make(binding.getRoot(), e.getMessage(), Snackbar.LENGTH_LONG).show();
Snackbar.make(binding.getRoot(), e.getMessage() != null ? e.getMessage() : "", Snackbar.LENGTH_LONG).show();
}
}
if (detailsChangeResourceLiveData != null) {
@ -274,6 +276,36 @@ public class DirectMessageSettingsFragment extends Fragment {
.setMultiple(true);
navController.navigate(actionGlobalUserSearch);
});
binding.muteMessagesLabel.setOnClickListener(v -> binding.muteMessages.toggle());
binding.muteMessages.setOnCheckedChangeListener((buttonView, isChecked) -> {
final LiveData<Resource<Object>> resourceLiveData = isChecked ? viewModel.mute() : viewModel.unmute();
handleMuteChangeResource(resourceLiveData, buttonView);
});
binding.muteMentionsLabel.setOnClickListener(v -> binding.muteMentions.toggle());
binding.muteMentions.setOnCheckedChangeListener((buttonView, isChecked) -> {
final LiveData<Resource<Object>> resourceLiveData = isChecked ? viewModel.muteMentions() : viewModel.unmuteMentions();
handleMuteChangeResource(resourceLiveData, buttonView);
});
}
private void handleMuteChangeResource(final LiveData<Resource<Object>> resourceLiveData, final CompoundButton buttonView) {
resourceLiveData.observe(getViewLifecycleOwner(), resource -> {
if (resource == null) return;
switch (resource.status) {
case SUCCESS:
buttonView.setEnabled(true);
break;
case ERROR:
buttonView.setEnabled(true);
if (resource.message != null) {
Snackbar.make(binding.getRoot(), resource.message, Snackbar.LENGTH_LONG).show();
}
break;
case LOADING:
buttonView.setEnabled(false);
break;
}
});
}
private void setupMembers() {

View File

@ -75,4 +75,24 @@ public interface DirectMessagesRepository {
@FormUrlEncoded
@POST("/api/v1/direct_v2/create_group_thread/")
Call<DirectThread> createThread(@FieldMap final Map<String, String> signedForm);
@FormUrlEncoded
@POST("/api/v1/direct_v2/threads/{threadId}/mute/")
Call<String> mute(@Path("threadId") String threadId,
@FieldMap final Map<String, String> form);
@FormUrlEncoded
@POST("/api/v1/direct_v2/threads/{threadId}/unmute/")
Call<String> unmute(@Path("threadId") String threadId,
@FieldMap final Map<String, String> form);
@FormUrlEncoded
@POST("/api/v1/direct_v2/threads/{threadId}/mute_mentions/")
Call<String> muteMentions(@Path("threadId") String threadId,
@FieldMap final Map<String, String> form);
@FormUrlEncoded
@POST("/api/v1/direct_v2/threads/{threadId}/unmute_mentions/")
Call<String> unmuteMentions(@Path("threadId") String threadId,
@FieldMap final Map<String, String> form);
}

View File

@ -17,7 +17,7 @@ public class DirectThread implements Serializable {
private final List<Long> adminUserIds;
private final List<DirectItem> items;
private final long lastActivityAt;
private final boolean muted;
private boolean muted;
private final boolean isPin;
private final boolean named;
private final boolean canonical;
@ -31,7 +31,7 @@ public class DirectThread implements Serializable {
private final long folder;
private final boolean vcMuted;
private final boolean isGroup;
private final boolean mentionsMuted;
private boolean mentionsMuted;
private final User inviter;
private final boolean hasOlder;
private final boolean hasNewer;
@ -138,6 +138,10 @@ public class DirectThread implements Serializable {
return muted;
}
public void setMuted(final boolean muted) {
this.muted = muted;
}
public boolean isPin() {
return isPin;
}
@ -194,6 +198,10 @@ public class DirectThread implements Serializable {
return mentionsMuted;
}
public void setMentionsMuted(final boolean mentionsMuted) {
this.mentionsMuted = mentionsMuted;
}
public User getInviter() {
return inviter;
}

View File

@ -59,14 +59,16 @@ public class DirectSettingsViewModel extends AndroidViewModel {
new Pair<>(Collections.emptyList(), Collections.emptyList()));
private final MutableLiveData<String> title = new MutableLiveData<>("");
private final MutableLiveData<List<Long>> adminUserIds = new MutableLiveData<>(Collections.emptyList());
private final MutableLiveData<Boolean> muted = new MutableLiveData<>(false);
private final MutableLiveData<Boolean> mentionsMuted = new MutableLiveData<>(false);
private final DirectMessagesService directMessagesService;
private DirectThread thread;
private final long userId;
private boolean viewerIsAdmin;
private final Resources resources;
private final FriendshipService friendshipService;
private final String csrfToken;
private DirectThread thread;
private boolean viewerIsAdmin;
private User viewer;
public DirectSettingsViewModel(final Application application) {
@ -103,6 +105,8 @@ public class DirectSettingsViewModel extends AndroidViewModel {
final List<Long> adminUserIds = thread.getAdminUserIds();
this.adminUserIds.postValue(adminUserIds);
viewerIsAdmin = adminUserIds.contains(userId);
muted.postValue(thread.isMuted());
mentionsMuted.postValue(thread.isMentionsMuted());
}
public boolean isGroup() {
@ -132,6 +136,10 @@ public class DirectSettingsViewModel extends AndroidViewModel {
return adminUserIds;
}
public LiveData<Boolean> getMuted() {
return muted;
}
public LiveData<Resource<Object>> updateTitle(final String newTitle) {
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
final Call<DirectThreadDetailsChangeResponse> addUsersRequest = directMessagesService
@ -156,7 +164,7 @@ public class DirectSettingsViewModel extends AndroidViewModel {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
if (!response.isSuccessful()) {
handleAdminChangeResponseError(response, data);
handleSettingChangeResponseError(response, data);
return;
}
Pair<List<User>, List<User>> usersValue = users.getValue();
@ -198,7 +206,7 @@ public class DirectSettingsViewModel extends AndroidViewModel {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
if (!response.isSuccessful()) {
handleAdminChangeResponseError(response, data);
handleSettingChangeResponseError(response, data);
return;
}
final List<Long> currentAdmins = adminUserIds.getValue();
@ -225,7 +233,7 @@ public class DirectSettingsViewModel extends AndroidViewModel {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
if (!response.isSuccessful()) {
handleAdminChangeResponseError(response, data);
handleSettingChangeResponseError(response, data);
return;
}
final List<Long> currentAdmins = adminUserIds.getValue();
@ -244,8 +252,124 @@ public class DirectSettingsViewModel extends AndroidViewModel {
return data;
}
private void handleAdminChangeResponseError(@NonNull final Response<String> response,
final MutableLiveData<Resource<Object>> data) {
public LiveData<Resource<Object>> mute() {
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
data.postValue(Resource.loading(null));
if (thread.isMuted()) {
data.postValue(Resource.success(new Object()));
return data;
}
final Call<String> request = directMessagesService.mute(thread.getThreadId());
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
if (!response.isSuccessful()) {
handleSettingChangeResponseError(response, data);
return;
}
thread.setMuted(true);
muted.postValue(true);
data.postValue(Resource.success(new Object()));
}
@Override
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
Log.e(TAG, "onFailure: ", t);
data.postValue(Resource.error(t.getMessage(), null));
}
});
return data;
}
public LiveData<Resource<Object>> unmute() {
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
data.postValue(Resource.loading(null));
if (!thread.isMuted()) {
data.postValue(Resource.success(new Object()));
return data;
}
final Call<String> request = directMessagesService.unmute(thread.getThreadId());
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
if (!response.isSuccessful()) {
handleSettingChangeResponseError(response, data);
return;
}
thread.setMuted(false);
muted.postValue(false);
data.postValue(Resource.success(new Object()));
}
@Override
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
Log.e(TAG, "onFailure: ", t);
data.postValue(Resource.error(t.getMessage(), null));
}
});
return data;
}
public LiveData<Resource<Object>> muteMentions() {
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
data.postValue(Resource.loading(null));
if (thread.isMentionsMuted()) {
data.postValue(Resource.success(new Object()));
return data;
}
final Call<String> request = directMessagesService.muteMentions(thread.getThreadId());
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
if (!response.isSuccessful()) {
handleSettingChangeResponseError(response, data);
return;
}
thread.setMentionsMuted(true);
mentionsMuted.postValue(true);
data.postValue(Resource.success(new Object()));
}
@Override
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
Log.e(TAG, "onFailure: ", t);
data.postValue(Resource.error(t.getMessage(), null));
}
});
return data;
}
public LiveData<Resource<Object>> unmuteMentions() {
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
data.postValue(Resource.loading(null));
if (!thread.isMentionsMuted()) {
data.postValue(Resource.success(new Object()));
return data;
}
final Call<String> request = directMessagesService.unmuteMentions(thread.getThreadId());
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
if (!response.isSuccessful()) {
handleSettingChangeResponseError(response, data);
return;
}
thread.setMentionsMuted(false);
mentionsMuted.postValue(false);
data.postValue(Resource.success(new Object()));
}
@Override
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
Log.e(TAG, "onFailure: ", t);
data.postValue(Resource.error(t.getMessage(), null));
}
});
return data;
}
private void handleSettingChangeResponseError(@NonNull final Response<String> response,
final MutableLiveData<Resource<Object>> data) {
final ResponseBody errorBody = response.errorBody();
if (errorBody == null) {
handleErrorResponse(response, data);

View File

@ -317,4 +317,36 @@ public class DirectMessagesService extends BaseService {
final Map<String, String> signedForm = Utils.sign(formBuilder.build());
return repository.createThread(signedForm);
}
public Call<String> mute(@NonNull final String threadId) {
final ImmutableMap<String, String> form = ImmutableMap.of(
"_csrftoken", csrfToken,
"_uuid", deviceUuid
);
return repository.mute(threadId, form);
}
public Call<String> unmute(@NonNull final String threadId) {
final ImmutableMap<String, String> form = ImmutableMap.of(
"_csrftoken", csrfToken,
"_uuid", deviceUuid
);
return repository.unmute(threadId, form);
}
public Call<String> muteMentions(@NonNull final String threadId) {
final ImmutableMap<String, String> form = ImmutableMap.of(
"_csrftoken", csrfToken,
"_uuid", deviceUuid
);
return repository.muteMentions(threadId, form);
}
public Call<String> unmuteMentions(@NonNull final String threadId) {
final ImmutableMap<String, String> form = ImmutableMap.of(
"_csrftoken", csrfToken,
"_uuid", deviceUuid
);
return repository.unmuteMentions(threadId, form);
}
}

View File

@ -50,11 +50,11 @@
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/mute_messages_label"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:background="?selectableItemBackground"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp"
@ -70,18 +70,18 @@
android:id="@+id/mute_messages"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:paddingStart="0dp"
android:paddingEnd="8dp"
android:layout_margin="8dp"
app:layout_constraintBottom_toTopOf="@id/mute_mentions"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_edit_input_layout" />
<com.google.android.material.button.MaterialButton
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/mute_mentions_label"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp"
@ -97,44 +97,47 @@
android:id="@+id/mute_mentions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:paddingStart="0dp"
android:paddingEnd="8dp"
android:layout_margin="8dp"
app:layout_constraintBottom_toTopOf="@id/leave"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/mute_messages" />
<com.google.android.material.button.MaterialButton
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/leave"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:background="?selectableItemBackground"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp"
android:paddingBottom="12dp"
android:text="@string/dms_action_leave"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textColor="@color/red_600"
app:layout_constraintBottom_toTopOf="@id/add_members"
app:layout_constraintTop_toBottomOf="@id/mute_mentions" />
<com.google.android.material.button.MaterialButton
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/add_members"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:background="?selectableItemBackground"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp"
android:paddingBottom="12dp"
android:text="@string/add_members"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textColor="?android:textColorPrimary"
app:icon="@drawable/ic_add"
app:iconTint="?android:textColorPrimary"
app:drawableStartCompat="@drawable/ic_add"
app:drawableTint="?android:textColorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/leave" />