Partially fix build

This commit is contained in:
Niels Andriesse 2019-10-15 13:39:17 +11:00
parent 2f18c5bad2
commit a8c4fa22a3
16 changed files with 94 additions and 98 deletions

View File

@ -87,8 +87,8 @@ import org.whispersystems.libsignal.logging.SignalProtocolLoggerProvider;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import org.whispersystems.signalservice.loki.api.LokiAPIDatabaseProtocol;
import org.whispersystems.signalservice.loki.api.LokiGroupChat;
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI;
import org.whispersystems.signalservice.loki.api.LokiLongPoller;
import org.whispersystems.signalservice.loki.api.LokiP2PAPI;
import org.whispersystems.signalservice.loki.api.LokiP2PAPIDelegate;
@ -138,7 +138,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
private LokiRSSFeedPoller lokiNewsFeedPoller = null;
private LokiRSSFeedPoller lokiMessengerUpdatesFeedPoller = null;
private LokiPublicChatManager lokiPublicChatManager = null;
private LokiGroupChatAPI lokiGroupChatAPI = null;
private LokiPublicChatAPI lokiPublicChatAPI = null;
public SignalCommunicationModule communicationModule;
public MixpanelAPI mixpanel;
@ -253,16 +253,16 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
return lokiPublicChatManager;
}
public @Nullable LokiGroupChatAPI getLokiGroupChatAPI() {
if (lokiGroupChatAPI == null && IdentityKeyUtil.hasIdentityKey(this)) {
public @Nullable LokiPublicChatAPI getLokiPublicChatAPI() {
if (lokiPublicChatAPI == null && IdentityKeyUtil.hasIdentityKey(this)) {
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
LokiAPIDatabase apiDatabase = DatabaseFactory.getLokiAPIDatabase(this);
LokiUserDatabase userDatabase = DatabaseFactory.getLokiUserDatabase(this);
lokiGroupChatAPI = new LokiGroupChatAPI(userHexEncodedPublicKey, userPrivateKey, apiDatabase, userDatabase);
lokiPublicChatAPI = new LokiPublicChatAPI(userHexEncodedPublicKey, userPrivateKey, apiDatabase, userDatabase);
}
return lokiGroupChatAPI;
return lokiPublicChatAPI;
}
private void initializeSecurityProvider() {
@ -502,8 +502,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
}
public void createGroupChatsIfNeeded() {
List<LokiGroupChat> defaultChats = LokiGroupChat.Companion.defaultChats(BuildConfig.DEBUG);
for (LokiGroupChat chat : defaultChats) {
List<LokiPublicChat> defaultChats = LokiPublicChat.Companion.defaultChats(BuildConfig.DEBUG);
for (LokiPublicChat chat : defaultChats) {
long threadID = GroupManager.getThreadId(chat.getId(), this);
String migrationKey = chat.getId() + "_migrated";
boolean isChatMigrated = TextSecurePreferences.getBooleanPreference(this, migrationKey, false);

View File

@ -61,8 +61,8 @@ import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.loki.api.LokiGroupChat;
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI;
import org.whispersystems.signalservice.loki.utilities.Analytics;
import java.io.ByteArrayInputStream;
@ -383,7 +383,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
Analytics.Companion.getShared().track("Display Name Updated");
TextSecurePreferences.setProfileName(context, name);
LokiGroupChatAPI chatAPI = ApplicationContext.getInstance(context).getLokiGroupChatAPI();
LokiPublicChatAPI chatAPI = ApplicationContext.getInstance(context).getLokiPublicChatAPI();
if (chatAPI != null) {
Set<String> groupChatServers = DatabaseFactory.getLokiThreadDatabase(context).getAllGroupChatServers();
for (String server : groupChatServers) {

View File

@ -32,8 +32,8 @@ import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.loki.api.LokiGroupChat;
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI;
import java.util.List;
@ -200,7 +200,7 @@ public class QuoteView extends FrameLayout implements RecipientModifiedListener
// If we're in a group then try and use the display name in the group
if (conversationRecipient.isGroupRecipient()) {
long threadId = DatabaseFactory.getThreadDatabase(getContext()).getThreadIdFor(conversationRecipient);
LokiGroupChat chat = DatabaseFactory.getLokiThreadDatabase(getContext()).getGroupChat(threadId);
LokiPublicChat chat = DatabaseFactory.getLokiThreadDatabase(getContext()).getGroupChat(threadId);
if (chat != null) {
String senderDisplayName = DatabaseFactory.getLokiUserDatabase(getContext()).getServerDisplayName(chat.getId(), author.getAddress().serialize());
if (senderDisplayName != null) { quoteeDisplayName = senderDisplayName; }

View File

@ -106,8 +106,8 @@ import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.internal.util.concurrent.SettableFuture;
import org.whispersystems.signalservice.loki.api.LokiGroupChat;
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI;
import java.io.IOException;
import java.io.InputStream;
@ -410,14 +410,14 @@ public class ConversationFragment extends Fragment
boolean isGroupChat = recipient.isGroupRecipient();
if (isGroupChat) {
LokiGroupChat groupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getGroupChat(threadId);
LokiPublicChat groupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getGroupChat(threadId);
boolean isPublicChat = groupChat != null;
int selectedMessageCount = messageRecords.size();
boolean isSentByUser = ((MessageRecord)messageRecords.toArray()[0]).isOutgoing();
menu.findItem(R.id.menu_context_copy_public_key).setVisible(isPublicChat && selectedMessageCount == 1 && !isSentByUser);
menu.findItem(R.id.menu_context_reply).setVisible(isPublicChat && selectedMessageCount == 1);
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(getContext());
boolean userCanModerate = groupChat != null && LokiGroupChatAPI.Companion.isUserModerator(userHexEncodedPublicKey, groupChat.getChannel(), groupChat.getServer());
boolean userCanModerate = groupChat != null && LokiPublicChatAPI.Companion.isUserModerator(userHexEncodedPublicKey, groupChat.getChannel(), groupChat.getServer());
boolean isDeleteOptionVisible = isPublicChat && selectedMessageCount == 1 && (isSentByUser || userCanModerate);
menu.findItem(R.id.menu_context_delete_message).setVisible(isDeleteOptionVisible);
} else {
@ -513,7 +513,7 @@ public class ConversationFragment extends Fragment
builder.setCancelable(true);
// Loki - The delete option is only visible to the user in a group chat
LokiGroupChat groupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getGroupChat(threadId);
LokiPublicChat groupChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getGroupChat(threadId);
builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
@Override
@ -530,7 +530,7 @@ public class ConversationFragment extends Fragment
if (groupChat != null) {
final SettableFuture<?>[] future = { new SettableFuture<Unit>() };
LokiGroupChatAPI chatAPI = ApplicationContext.getInstance(getContext()).getLokiGroupChatAPI();
LokiPublicChatAPI chatAPI = ApplicationContext.getInstance(getContext()).getLokiPublicChatAPI();
boolean isSentByUser = messageRecord.isOutgoing();
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id);

View File

@ -114,8 +114,8 @@ 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.LokiGroupChat;
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI;
import java.util.Collections;
import java.util.HashSet;
@ -941,9 +941,9 @@ public class ConversationItem extends LinearLayout
int visibility = View.GONE;
// If we have a chat then use that to determine mod status
LokiGroupChat groupChat = DatabaseFactory.getLokiThreadDatabase(context).getGroupChat(messageRecord.getThreadId());
LokiPublicChat groupChat = DatabaseFactory.getLokiThreadDatabase(context).getGroupChat(messageRecord.getThreadId());
if (groupChat != null) {
boolean isModerator = LokiGroupChatAPI.Companion.isUserModerator(current.getRecipient().getAddress().toString(), groupChat.getChannel(), groupChat.getServer());
boolean isModerator = LokiPublicChatAPI.Companion.isUserModerator(current.getRecipient().getAddress().toString(), groupChat.getChannel(), groupChat.getServer());
visibility = isModerator ? View.VISIBLE : View.GONE;
}

View File

@ -45,8 +45,8 @@ import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
import org.whispersystems.signalservice.loki.api.LokiGroupChat;
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI;
import org.whispersystems.signalservice.loki.api.LokiPublicChat;
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI;
import java.io.IOException;
import java.util.ArrayList;
@ -290,7 +290,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
// Loki - All group messages should be directed to their servers
long threadID = GroupManager.getThreadIdFromGroupId(groupId, context);
LokiGroupChat chat = DatabaseFactory.getLokiThreadDatabase(context).getGroupChat(threadID);
LokiPublicChat chat = DatabaseFactory.getLokiThreadDatabase(context).getGroupChat(threadID);
if (chat != null) {
// We need to somehow maintain information that will allow the sender to map
// a Recipient to the correct public chat thread, and so this might be a bit hacky

View File

@ -1,13 +1,10 @@
package org.thoughtcrime.securesms.loki
import android.Manifest
import android.content.Intent
import android.os.Bundle
import android.util.Patterns
import android.view.MenuItem
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_account_details.*
import kotlinx.android.synthetic.main.fragment_add_public_chat.*
import network.loki.messenger.R
import nl.komponents.kovenant.ui.failUi
@ -15,16 +12,7 @@ import nl.komponents.kovenant.ui.successUi
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.ConversationActivity
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.DynamicTheme
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI
import org.whispersystems.signalservice.loki.utilities.Analytics
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
class AddPublicChatActivity : PassphraseRequiredActionBarActivity() {
private val dynamicTheme = DynamicTheme()

View File

@ -8,11 +8,9 @@ import network.loki.messenger.R
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.ConversationListActivity
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.api.crypto.ProfileCipher
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI
import org.whispersystems.signalservice.loki.utilities.Analytics
class DisplayNameActivity : BaseActionBarActivity() {
@ -46,9 +44,9 @@ class DisplayNameActivity : BaseActionBarActivity() {
startActivity(Intent(this, ConversationListActivity::class.java))
finish()
val chatAPI = ApplicationContext.getInstance(this).lokiGroupChatAPI
val chatAPI = ApplicationContext.getInstance(this).lokiPublicChatAPI
if (chatAPI != null && name != null) {
val servers = DatabaseFactory.getLokiThreadDatabase(this).getAllGroupChatServers()
val servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers()
servers.forEach { chatAPI.setDisplayName(name, it) }
}
}

View File

@ -7,7 +7,6 @@ import android.support.annotation.ColorRes
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.recipients.Recipient
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
import kotlin.math.roundToInt
@ -25,7 +24,7 @@ fun toPx(dp: Int, resources: Resources): Int {
}
fun isGroupRecipient(context: Context, recipient: String): Boolean {
return DatabaseFactory.getLokiThreadDatabase(context).getAllGroupChats().values.map { it.server }.contains(recipient)
return DatabaseFactory.getLokiThreadDatabase(context).getAllPublicChats().values.map { it.server }.contains(recipient)
}
fun getFriendPublicKeys(context: Context, devicePublicKeys: Set<String>): Set<String> {

View File

@ -9,7 +9,7 @@ import org.whispersystems.signalservice.loki.api.LokiAPI
object LokiAPIUtilities {
fun populateUserIDCacheIfNeeded(threadID: Long, context: Context) {
if (LokiAPI.userIDCache[threadID] != null) { return }
if (LokiAPI.userHexEncodedPublicKeyCache[threadID] != null) { return }
val result = mutableSetOf<String>()
val messageDatabase = DatabaseFactory.getMmsSmsDatabase(context)
val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID))
@ -24,6 +24,6 @@ object LokiAPIUtilities {
}
reader.close()
result.add(TextSecurePreferences.getLocalNumber(context))
LokiAPI.userIDCache[threadID] = result
LokiAPI.userHexEncodedPublicKeyCache[threadID] = result
}
}

View File

@ -7,20 +7,17 @@ import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.functional.bind
import nl.komponents.kovenant.functional.map
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.DatabaseContentProviders
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.util.GroupUtil
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.Util
import org.whispersystems.signalservice.loki.api.LokiGroupChat
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI
import java.util.HashSet
import org.whispersystems.signalservice.loki.api.LokiPublicChat
import java.util.*
class LokiPublicChatManager(private val context: Context) {
private var chats = mutableMapOf<Long, LokiGroupChat>()
private val pollers = mutableMapOf<Long, LokiGroupChatPoller>()
private var chats = mutableMapOf<Long, LokiPublicChat>()
private val pollers = mutableMapOf<Long, LokiPublicChatPoller>()
private val observers = mutableMapOf<Long, ContentObserver>()
private var isPolling = false
@ -28,7 +25,7 @@ class LokiPublicChatManager(private val context: Context) {
refreshChatsAndPollers()
for ((threadId, chat) in chats) {
val poller = pollers[threadId] ?: LokiGroupChatPoller(context, chat)
val poller = pollers[threadId] ?: LokiPublicChatPoller(context, chat)
poller.startIfNeeded()
listenToThreadDeletion(threadId)
if (!pollers.containsKey(threadId)) { pollers[threadId] = poller }
@ -41,8 +38,8 @@ class LokiPublicChatManager(private val context: Context) {
isPolling = false
}
public fun addChat(server: String, channel: Long): Promise<LokiGroupChat, Exception> {
val groupChatAPI = ApplicationContext.getInstance(context).lokiGroupChatAPI ?: return Promise.ofFail(IllegalStateException("LokiGroupChatAPI is not set!"))
public fun addChat(server: String, channel: Long): Promise<LokiPublicChat, Exception> {
val groupChatAPI = ApplicationContext.getInstance(context).lokiPublicChatAPI ?: return Promise.ofFail(IllegalStateException("LokiPublicChatAPI is not set!"))
return groupChatAPI.getAuthToken(server).bind {
groupChatAPI.getChannelInfo(channel, server)
}.map {
@ -50,19 +47,19 @@ class LokiPublicChatManager(private val context: Context) {
}
}
public fun addChat(server: String, channel: Long, name: String): LokiGroupChat {
val chat = LokiGroupChat(channel, server, name, true)
public fun addChat(server: String, channel: Long, name: String): LokiPublicChat {
val chat = LokiPublicChat(channel, server, name, true)
var threadID = GroupManager.getThreadId(chat.id, context)
// Create the group if we don't have one
if (threadID < 0) {
val result = GroupManager.createGroup(chat.id, context, HashSet(), null, chat.displayName, false)
threadID = result.threadId
}
DatabaseFactory.getLokiThreadDatabase(context).setGroupChat(chat, threadID)
DatabaseFactory.getLokiThreadDatabase(context).setPublicChat(chat, threadID)
// Set our name on the server
val displayName = TextSecurePreferences.getProfileName(context)
if (!TextUtils.isEmpty(displayName)) {
ApplicationContext.getInstance(context).lokiGroupChatAPI?.setDisplayName(server, displayName)
ApplicationContext.getInstance(context).lokiPublicChatAPI?.setDisplayName(server, displayName)
}
// Start polling
Util.runOnMain{ startPollersIfNeeded() }
@ -71,7 +68,7 @@ class LokiPublicChatManager(private val context: Context) {
}
private fun refreshChatsAndPollers() {
val chatsInDB = DatabaseFactory.getLokiThreadDatabase(context).getAllGroupChats()
val chatsInDB = DatabaseFactory.getLokiThreadDatabase(context).getAllPublicChats()
val removedChatThreadIds = chats.keys.filter { !chatsInDB.keys.contains(it) }
removedChatThreadIds.forEach { pollers.remove(it)?.stop() }
@ -91,7 +88,7 @@ class LokiPublicChatManager(private val context: Context) {
apiDatabase.removeLastMessageServerID(chat.channel, chat.server)
}
DatabaseFactory.getLokiThreadDatabase(context).removeGroupChat(threadID)
DatabaseFactory.getLokiThreadDatabase(context).removePublicChat(threadID)
pollers.remove(threadID)?.stop()
observers.remove(threadID)
startPollersIfNeeded()

View File

@ -21,23 +21,23 @@ import org.whispersystems.signalservice.api.messages.SignalServiceContent
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
import org.whispersystems.signalservice.api.messages.SignalServiceGroup
import org.whispersystems.signalservice.api.push.SignalServiceAddress
import org.whispersystems.signalservice.loki.api.LokiGroupChat
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI
import org.whispersystems.signalservice.loki.api.LokiGroupMessage
import org.whispersystems.signalservice.loki.api.LokiPublicChat
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI
import org.whispersystems.signalservice.loki.api.LokiPublicChatMessage
class LokiGroupChatPoller(private val context: Context, private val group: LokiGroupChat) {
class LokiPublicChatPoller(private val context: Context, private val group: LokiPublicChat) {
private val handler = Handler()
private var hasStarted = false
// region Convenience
private val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
private val api: LokiGroupChatAPI
private val api: LokiPublicChatAPI
get() = {
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
val lokiUserDatabase = DatabaseFactory.getLokiUserDatabase(context)
LokiGroupChatAPI(userHexEncodedPublicKey, userPrivateKey, lokiAPIDatabase, lokiUserDatabase)
LokiPublicChatAPI(userHexEncodedPublicKey, userPrivateKey, lokiAPIDatabase, lokiUserDatabase)
}()
// endregion
@ -94,7 +94,7 @@ class LokiGroupChatPoller(private val context: Context, private val group: LokiG
// region Polling
private fun pollForNewMessages() {
fun processIncomingMessage(message: LokiGroupMessage) {
fun processIncomingMessage(message: LokiPublicChatMessage) {
val id = group.id.toByteArray()
val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, null, null, null)
val quote: SignalServiceDataMessage.Quote?
@ -113,7 +113,7 @@ class LokiGroupChatPoller(private val context: Context, private val group: LokiG
PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.of(message.serverID))
}
}
fun processOutgoingMessage(message: LokiGroupMessage) {
fun processOutgoingMessage(message: LokiPublicChatMessage) {
val messageServerID = message.serverID ?: return
val lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context)
val isDuplicate = lokiMessageDatabase.getMessageID(messageServerID) != null

View File

@ -9,11 +9,10 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.recipients.Recipient
import org.whispersystems.signalservice.internal.util.JsonUtil
import org.whispersystems.signalservice.loki.api.LokiGroupChat
import org.whispersystems.signalservice.loki.api.LokiPublicChat
import org.whispersystems.signalservice.loki.messaging.LokiThreadDatabaseProtocol
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
import org.whispersystems.signalservice.loki.messaging.LokiThreadSessionResetStatus
import java.lang.Exception
class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiThreadDatabaseProtocol {
var delegate: LokiThreadDatabaseDelegate? = null
@ -92,17 +91,17 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
notifyConversationListeners(threadID)
}
fun getAllGroupChats(): Map<Long, LokiGroupChat> {
fun getAllPublicChats(): Map<Long, LokiPublicChat> {
val database = databaseHelper.readableDatabase
var cursor: Cursor? = null
try {
val map = mutableMapOf<Long, LokiGroupChat>()
val map = mutableMapOf<Long, LokiPublicChat>()
cursor = database.rawQuery("select * from $groupChatMappingTableName", null)
while (cursor != null && cursor.moveToNext()) {
val threadID = cursor.getLong(Companion.threadID)
val string = cursor.getString(groupChatJSON)
val chat = LokiGroupChat.fromJSON(string)
val chat = LokiPublicChat.fromJSON(string)
if (chat != null) { map[threadID] = chat }
}
return map
@ -115,20 +114,20 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
return mapOf()
}
fun getAllGroupChatServers(): Set<String> {
return getAllGroupChats().values.fold(setOf<String>()) { set, chat -> set.plus(chat.server) }
fun getAllPublicChatServers(): Set<String> {
return getAllPublicChats().values.fold(setOf<String>()) { set, chat -> set.plus(chat.server) }
}
override fun getGroupChat(threadID: Long): LokiGroupChat? {
override fun getPublicChat(threadID: Long): LokiPublicChat? {
if (threadID < 0) { return null }
val database = databaseHelper.readableDatabase
return database.get(groupChatMappingTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
val string = cursor.getString(groupChatJSON)
LokiGroupChat.fromJSON(string)
LokiPublicChat.fromJSON(string)
}
}
override fun setGroupChat(groupChat: LokiGroupChat, threadID: Long) {
override fun setPublicChat(groupChat: LokiPublicChat, threadID: Long) {
if (threadID < 0) { return }
val database = databaseHelper.writableDatabase
@ -138,7 +137,7 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
database.insertOrUpdate(groupChatMappingTableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
}
override fun removeGroupChat(threadID: Long) {
override fun removePublicChat(threadID: Long) {
databaseHelper.writableDatabase.delete(groupChatMappingTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
}
}

View File

@ -8,31 +8,32 @@ import android.util.Range
import network.loki.messenger.R
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI
import java.util.regex.Pattern
object MentionUtilities {
@JvmStatic
fun highlightMentions(text: CharSequence, isGroupThread: Boolean, context: Context): String {
return MentionUtilities.highlightMentions(text, false, isGroupThread, context).toString() // isOutgoingMessage is irrelevant
fun highlightMentions(text: CharSequence, threadID: Long, context: Context): String {
return MentionUtilities.highlightMentions(text, false, threadID, context).toString() // isOutgoingMessage is irrelevant
}
@JvmStatic
fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, isGroupThread: Boolean, context: Context): SpannableString {
fun highlightMentions(text: CharSequence, isOutgoingMessage: Boolean, threadID: Long, context: Context): SpannableString {
var text = text
val pattern = Pattern.compile("@[0-9a-fA-F]*")
var matcher = pattern.matcher(text)
val mentions = mutableListOf<Range<Int>>()
var startIndex = 0
if (matcher.find(startIndex) && isGroupThread) {
val publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
if (matcher.find(startIndex)) {
while (true) {
val userID = text.subSequence(matcher.start() + 1, matcher.end()).toString() // +1 to get rid of the @
val userDisplayName: String? = if (userID.toLowerCase() == TextSecurePreferences.getLocalNumber(context).toLowerCase()) {
TextSecurePreferences.getProfileName(context)
} else if (publicChat != null) {
DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChat.id, userID)
} else {
val publicChatID = LokiGroupChatAPI.publicChatServer + "." + LokiGroupChatAPI.publicChatServerID
DatabaseFactory.getLokiUserDatabase(context).getServerDisplayName(publicChatID, userID)
"" // TODO: Implement
}
if (userDisplayName != null) {
text = text.subSequence(0, matcher.start()).toString() + "@" + userDisplayName + text.subSequence(matcher.end(), text.length)

View File

@ -13,7 +13,10 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
class UserSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
private var users = listOf<Tuple2<String, String>>()
set(newValue) { field = newValue; userSelectionViewAdapter.users = newValue }
private var hasGroupContext = false
var publicChatServer: String? = null
set(newValue) { field = newValue; userSelectionViewAdapter.publicChatServer = publicChatServer }
var publicChatChannel: Long? = null
set(newValue) { field = newValue; userSelectionViewAdapter.publicChatChannel = publicChatChannel }
var onUserSelected: ((Tuple2<String, String>) -> Unit)? = null
private val userSelectionViewAdapter by lazy { Adapter(context) }
@ -21,7 +24,8 @@ class UserSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: In
private class Adapter(private val context: Context) : BaseAdapter() {
var users = listOf<Tuple2<String, String>>()
set(newValue) { field = newValue; notifyDataSetChanged() }
var hasGroupContext = false
var publicChatServer: String? = null
var publicChatChannel: Long? = null
override fun getCount(): Int {
return users.count()
@ -39,7 +43,8 @@ class UserSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: In
val cell = cellToBeReused as UserSelectionViewCell? ?: UserSelectionViewCell.inflate(LayoutInflater.from(context), parent)
val user = getItem(position)
cell.user = user
cell.hasGroupContext = hasGroupContext
cell.publicChatServer = publicChatServer
cell.publicChatChannel = publicChatChannel
return cell
}
}
@ -56,7 +61,11 @@ class UserSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: In
}
fun show(users: List<Tuple2<String, String>>, threadID: Long) {
hasGroupContext = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)!!.isGroupRecipient
val publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
if (publicChat != null) {
publicChatServer = publicChat.server
publicChatChannel = publicChat.channel
}
this.users = users
val layoutParams = this.layoutParams as ViewGroup.LayoutParams
layoutParams.height = toPx(6 + Math.min(users.count(), 4) * 52, resources)

View File

@ -11,12 +11,13 @@ import android.widget.LinearLayout
import kotlinx.android.synthetic.main.cell_user_selection_view.view.*
import network.loki.messenger.R
import nl.komponents.kovenant.combine.Tuple2
import org.whispersystems.signalservice.loki.api.LokiGroupChatAPI
import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI
class UserSelectionViewCell(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
var user = Tuple2("", "")
set(newValue) { field = newValue; update() }
var hasGroupContext = false
var publicChatServer: String? = null
var publicChatChannel: Long? = null
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context) : this(context, null)
@ -42,7 +43,11 @@ class UserSelectionViewCell(context: Context, attrs: AttributeSet?, defStyleAttr
private fun update() {
displayNameTextView.text = user.second
profilePictureImageView.update(user.first)
val isUserModerator = LokiGroupChatAPI.isUserModerator(user.first, LokiGroupChatAPI.publicChatServerID, LokiGroupChatAPI.publicChatServer)
moderatorIconImageView.visibility = if (isUserModerator && hasGroupContext) View.VISIBLE else View.GONE
if (publicChatServer != null && publicChatChannel != null) {
val isUserModerator = LokiPublicChatAPI.isUserModerator(user.first, publicChatChannel!!, publicChatServer!!)
moderatorIconImageView.visibility = if (isUserModerator) View.VISIBLE else View.GONE
} else {
moderatorIconImageView.visibility = View.GONE
}
}
}