Implement moderator tags

pull/24/head
Niels Andriesse 5 years ago
parent 7cc7f907fe
commit b67efcf2ab

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="512dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:pathData="m419.25,369.977h-326.5c-4.988,0 -9.648,-2.465 -12.457,-6.586 -43.078,-63.172 -46.383,-184.691 -46.633,-202.73 -0.016,-0.707 -0.023,-1.422 -0.023,-2.133 0,-8.316 6.734,-15.063 15.051,-15.078h0.031c8.301,0 15.047,6.715 15.078,15.02 0,0.102 0.004,0.992 0.039,2.57 1.328,42.902 36.645,77.391 79.863,77.391 44.059,0 79.902,-35.844 79.902,-79.902 0,-8.328 6.754,-15.078 15.078,-15.078h34.637c8.328,0 15.078,6.75 15.078,15.078 0,44.059 35.848,79.902 79.906,79.902 43.258,0 78.598,-34.551 79.867,-77.508 0.027,-1.508 0.035,-2.352 0.035,-2.449 0.031,-8.309 6.773,-15.023 15.078,-15.023h0.027c8.316,0.016 15.051,6.762 15.051,15.078 0,0.715 -0.008,1.426 -0.02,2.137 -0.254,18.035 -3.559,139.559 -46.633,202.73 -2.809,4.117 -7.473,6.582 -12.457,6.582zM419.25,369.977"
android:fillColor="#fff780"/>
<path
android:pathData="m463.309,143.449c-0.008,0 -0.016,0 -0.027,0 -8.301,0 -15.047,6.715 -15.078,15.02 0,0.102 -0.004,0.945 -0.035,2.453 -1.27,42.953 -36.609,77.508 -79.867,77.508 -44.059,0 -79.902,-35.844 -79.902,-79.902 0,-8.328 -6.754,-15.078 -15.078,-15.078h-17.316v226.523h163.246c4.988,0 9.648,-2.465 12.457,-6.582 43.078,-63.172 46.383,-184.695 46.633,-202.73 0.016,-0.707 0.023,-1.422 0.023,-2.133 -0.004,-8.316 -6.738,-15.063 -15.055,-15.078zM463.309,143.449"
android:fillColor="#ffc02e"/>
<path
android:pathData="m256,92c-26.863,0 -48.719,21.855 -48.719,48.719s21.855,48.715 48.719,48.715 48.719,-21.852 48.719,-48.715 -21.855,-48.719 -48.719,-48.719zM256,92"
android:fillColor="#ffc02e"/>
<path
android:pathData="m256.004,92v97.438c26.863,-0.004 48.715,-21.855 48.715,-48.719s-21.855,-48.715 -48.715,-48.719zM256.004,92"
android:fillColor="#ffa73b"/>
<path
android:pathData="m48.719,129.598c-26.863,0 -48.719,21.855 -48.719,48.719 0,26.863 21.855,48.719 48.719,48.719s48.715,-21.855 48.715,-48.719c0,-26.863 -21.852,-48.719 -48.715,-48.719zM48.719,129.598"
android:fillColor="#ffc02e"/>
<path
android:pathData="m463.281,129.598c-26.863,0 -48.715,21.855 -48.715,48.719 0,26.859 21.852,48.715 48.715,48.715s48.719,-21.855 48.719,-48.715c0,-26.863 -21.855,-48.719 -48.719,-48.719zM463.281,129.598"
android:fillColor="#ffa73b"/>
<path
android:pathData="m419.25,419.441h-326.5c-8.328,0 -15.078,-6.75 -15.078,-15.078v-44.965h356.656v44.965c0,8.328 -6.75,15.078 -15.078,15.078zM419.25,419.441"
android:fillColor="#ffc02e"/>
<path
android:pathData="m256.004,419.441h163.246c8.328,0 15.078,-6.75 15.078,-15.078v-44.965h-178.324zM256.004,419.441"
android:fillColor="#ffa73b"/>
</vector>

@ -23,7 +23,7 @@
android:clipToPadding="false"
android:clipChildren="false">
<FrameLayout
<RelativeLayout
android:id="@+id/contact_photo_container"
android:layout_width="36dp"
android:layout_height="wrap_content"
@ -39,7 +39,15 @@
android:cropToPadding="true"
android:contentDescription="@string/conversation_item_received__contact_photo_description" />
</FrameLayout>
<ImageView
android:id="@+id/moderator_icon_image_view"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/icon_crown"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"

@ -413,8 +413,8 @@ public class ConversationFragment extends Fragment
boolean isSentByUser = ((MessageRecord)messageRecords.toArray()[0]).isOutgoing();
menu.findItem(R.id.menu_context_copy_public_key).setVisible(isLokiPublicChat && selectedMessageCount == 1 && !isSentByUser);
menu.findItem(R.id.menu_context_reply).setVisible(isLokiPublicChat && selectedMessageCount == 1);
LokiAPIDatabase lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(getContext());
boolean userCanModerate = lokiAPIDatabase.isModerator(LokiGroupChatAPI.getPublicChatServerID(), LokiGroupChatAPI.getPublicChatServer());
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(getContext());
boolean userCanModerate = LokiGroupChatAPI.Companion.isUserModerator(userHexEncodedPublicKey, LokiGroupChatAPI.getPublicChatServerID(), LokiGroupChatAPI.getPublicChatServer());
boolean isDeleteOptionVisible = isLokiPublicChat && selectedMessageCount == 1 && (isSentByUser || userCanModerate);
menu.findItem(R.id.menu_context_delete_message).setVisible(isDeleteOptionVisible);
} else {

@ -45,6 +45,7 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@ -99,9 +100,19 @@ import org.thoughtcrime.securesms.mms.TextSlide;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.stickers.StickerUrl;
import org.thoughtcrime.securesms.util.*;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.LongClickCopySpan;
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
import org.thoughtcrime.securesms.util.SearchUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
import java.util.Collections;
import java.util.HashSet;
@ -142,6 +153,7 @@ public class ConversationItem extends LinearLayout
private TextView groupSenderProfileName;
private View groupSenderHolder;
private AvatarImageView contactPhoto;
private ImageView moderatorIconImageView;
private ViewGroup contactPhotoHolder;
private AlertView alertView;
private ViewGroup container;
@ -198,6 +210,7 @@ public class ConversationItem extends LinearLayout
this.groupSenderProfileName = findViewById(R.id.group_message_sender_profile);
this.alertView = findViewById(R.id.indicators_parent);
this.contactPhoto = findViewById(R.id.contact_photo);
this.moderatorIconImageView = findViewById(R.id.moderator_icon_image_view);
this.contactPhotoHolder = findViewById(R.id.contact_photo_container);
this.bodyBubble = findViewById(R.id.body_bubble);
this.mediaThumbnailStub = new Stub<>(findViewById(R.id.image_view_stub));
@ -921,14 +934,25 @@ public class ConversationItem extends LinearLayout
if (!next.isPresent() || next.get().isUpdate() || !current.getRecipient().getAddress().equals(next.get().getRecipient().getAddress())) {
contactPhoto.setVisibility(VISIBLE);
int visibility;
if (conversationRecipient.getName() != null && conversationRecipient.getName().equals("Loki Public Chat")) {
boolean isModerator = LokiGroupChatAPI.Companion.isUserModerator(TextSecurePreferences.getLocalNumber(getContext()), LokiGroupChatAPI.getPublicChatServerID(), LokiGroupChatAPI.getPublicChatServer());
visibility = isModerator ? View.VISIBLE : View.GONE;
} else {
visibility = View.GONE;
}
moderatorIconImageView.setVisibility(visibility);
} else {
contactPhoto.setVisibility(GONE);
moderatorIconImageView.setVisibility(GONE);
}
} else {
groupSenderHolder.setVisibility(GONE);
if (contactPhotoHolder != null) {
contactPhotoHolder.setVisibility(GONE);
moderatorIconImageView.setVisibility(GONE);
}
}
}

@ -129,7 +129,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL(LokiAPIDatabase.getCreateGroupChatAuthTokenTableCommand());
db.execSQL(LokiAPIDatabase.getCreateLastMessageServerIDTableCommand());
db.execSQL(LokiAPIDatabase.getCreateLastDeletionServerIDTableCommand());
db.execSQL(LokiAPIDatabase.getCreateModerationPermissionTableCommand());
db.execSQL(LokiPreKeyBundleDatabase.getCreateTableCommand());
db.execSQL(LokiPreKeyRecordDatabase.getCreateTableCommand());
db.execSQL(LokiMessageDatabase.getCreateTableCommand());

@ -45,11 +45,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
private val lastDeletionServerIDCacheIndex = "loki_api_last_deletion_server_id_cache_index"
private val lastDeletionServerID = "last_deletion_server_id"
@JvmStatic val createLastDeletionServerIDTableCommand = "CREATE TABLE $lastDeletionServerIDCache ($lastDeletionServerIDCacheIndex STRING PRIMARY KEY, $lastDeletionServerID INTEGER DEFAULT 0);"
// Moderation permission cache
private val moderationPermissionCache = "loki_api_moderation_permission_cache"
private val moderationPermissionCacheIndex = "loki_api_moderation_permission_cache_index"
private val isModerator = "is_moderator"
@JvmStatic val createModerationPermissionTableCommand = "CREATE TABLE $moderationPermissionCache ($moderationPermissionCacheIndex STRING PRIMARY KEY, $isModerator INTEGER DEFAULT 0);"
}
override fun getSwarmCache(hexEncodedPublicKey: String): Set<LokiAPITarget>? {
@ -146,21 +141,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
val row = wrap(mapOf( lastDeletionServerIDCacheIndex to index, lastDeletionServerID to newValue.toString() ))
database.insertOrUpdate(lastDeletionServerIDCache, row, "$lastDeletionServerIDCacheIndex = ?", wrap(index))
}
fun isModerator(group: Long, server: String): Boolean {
val database = databaseHelper.readableDatabase
val index = "$server.$group"
return database.get(moderationPermissionCache, "$moderationPermissionCacheIndex = ?", wrap(index)) { cursor ->
cursor.getInt(isModerator)
} == 1
}
fun setIsModerator(group: Long, server: String, newValue: Boolean) {
val database = databaseHelper.writableDatabase
val index = "$server.$group"
val row = wrap(mapOf( moderationPermissionCacheIndex to index, isModerator to (if (newValue) 1 else 0).toString() ))
database.insertOrUpdate(moderationPermissionCache, row, "$moderationPermissionCacheIndex = ?", wrap(index))
}
}
// region Convenience

@ -58,11 +58,11 @@ class LokiGroupChatPoller(private val context: Context, private val group: LokiG
}
}
private val pollForModerationPermissionTask = object : Runnable {
private val pollForModeratorsTask = object : Runnable {
override fun run() {
pollForModerationPermission()
handler.postDelayed(this, pollForModerationPermissionInterval)
pollForModerators()
handler.postDelayed(this, pollForModeratorsInterval)
}
}
// endregion
@ -71,7 +71,7 @@ class LokiGroupChatPoller(private val context: Context, private val group: LokiG
companion object {
private val pollForNewMessagesInterval: Long = 4 * 1000
private val pollForDeletedMessagesInterval: Long = 20 * 1000
private val pollForModerationPermissionInterval: Long = 10 * 60 * 1000
private val pollForModeratorsInterval: Long = 10 * 60 * 1000
}
// endregion
@ -80,14 +80,14 @@ class LokiGroupChatPoller(private val context: Context, private val group: LokiG
if (hasStarted) return
pollForNewMessagesTask.run()
pollForDeletedMessagesTask.run()
pollForModerationPermissionTask.run()
pollForModeratorsTask.run()
hasStarted = true
}
fun stop() {
handler.removeCallbacks(pollForNewMessagesTask)
handler.removeCallbacks(pollForDeletedMessagesTask)
handler.removeCallbacks(pollForModerationPermissionTask)
handler.removeCallbacks(pollForModeratorsTask)
hasStarted = false
}
// endregion
@ -189,11 +189,8 @@ class LokiGroupChatPoller(private val context: Context, private val group: LokiG
}
}
private fun pollForModerationPermission() {
api.userHasModerationPermission(group.serverID, group.server).success { isModerator ->
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
lokiAPIDatabase.setIsModerator(group.serverID, group.server, isModerator)
}
private fun pollForModerators() {
api.getModerators(group.serverID, group.server)
}
// endregion
}
Loading…
Cancel
Save