diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 20a03d0eee..2a07a59a77 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -23,14 +23,19 @@ import org.session.libsignal.libsignal.util.guava.Optional import org.session.libsignal.service.api.messages.SignalServiceAttachmentPointer import org.session.libsignal.service.api.messages.SignalServiceGroup import org.session.libsignal.service.internal.push.SignalServiceProtos +import org.session.libsignal.service.loki.api.opengroups.PublicChat import org.thoughtcrime.securesms.crypto.IdentityKeyUtil +import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper +import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase +import org.thoughtcrime.securesms.loki.utilities.get +import org.thoughtcrime.securesms.loki.utilities.getString import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage import org.thoughtcrime.securesms.mms.PartAuthority import org.thoughtcrime.securesms.sms.IncomingGroupMessage import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.thoughtcrime.securesms.util.GroupUtil -class Storage(val context: Context): StorageProtocol { +class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol { override fun getUserPublicKey(): String? { return TextSecurePreferences.getLocalNumber(context) } @@ -122,11 +127,18 @@ class Storage(val context: Context): StorageProtocol { } override fun getOpenGroup(threadID: String): OpenGroup? { - TODO("Not yet implemented") + if (threadID.toInt() < 0) { return null } + val database = databaseHelper.readableDatabase + return database.get(LokiThreadDatabase.publicChatTable, "${LokiThreadDatabase.threadID} = ?", arrayOf( threadID )) { cursor -> + val publicChatAsJSON = cursor.getString(LokiThreadDatabase.publicChat) + OpenGroup.fromJSON(publicChatAsJSON) + } } - override fun getThreadID(openGroupID: String): String? { - TODO("Not yet implemented") + override fun getThreadID(openGroupID: String): String { + val address = Address.fromSerialized(openGroupID) + val recipient = Recipient.from(context, address, false) + return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient).toString() } override fun getOpenGroupPublicKey(server: String): String? { diff --git a/libsession/src/main/java/org/session/libsession/messaging/contacts/ContactAccessor.java b/libsession/src/main/java/org/session/libsession/messaging/contacts/ContactAccessor.java deleted file mode 100644 index e0fd4aa2c7..0000000000 --- a/libsession/src/main/java/org/session/libsession/messaging/contacts/ContactAccessor.java +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Copyright (C) 2011 Whisper Systems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.session.libsession.messaging.contacts; - -import android.content.Context; -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; - -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.GroupDatabase; -import org.thoughtcrime.securesms.util.TextSecurePreferences; - -import java.util.LinkedList; -import java.util.List; - -import network.loki.messenger.R; - -import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; - -/** - * This class was originally a layer of indirection between - * ContactAccessorNewApi and ContactAccesorOldApi, which corresponded - * to the API changes between 1.x and 2.x. - * - * Now that we no longer support 1.x, this class mostly serves as a place - * to encapsulate Contact-related logic. It's still a singleton, mostly - * just because that's how it's currently called from everywhere. - * - * @author Moxie Marlinspike - */ - -public class ContactAccessor { - - private static final ContactAccessor instance = new ContactAccessor(); - - public static synchronized ContactAccessor getInstance() { - return instance; - } - - public String getNameFromContact(Context context, Uri uri) { - return "Anonymous"; - } - - public ContactData getContactData(Context context, Uri uri) { - return getContactData(context, getNameFromContact(context, uri), Long.parseLong(uri.getLastPathSegment())); - } - - private ContactData getContactData(Context context, String displayName, long id) { - return new ContactData(id, displayName); - } - - public List getNumbersForThreadSearchFilter(Context context, String constraint) { - LinkedList numberList = new LinkedList<>(); - - GroupDatabase.Reader reader = null; - GroupRecord record; - - try { - reader = DatabaseFactory.getGroupDatabase(context).getGroupsFilteredByTitle(constraint); - - while ((record = reader.getNext()) != null) { - numberList.add(record.getEncodedId()); - } - } finally { - if (reader != null) - reader.close(); - } - - if (context.getString(R.string.note_to_self).toLowerCase().contains(constraint.toLowerCase()) && - !numberList.contains(TextSecurePreferences.getLocalNumber(context))) - { - numberList.add(TextSecurePreferences.getLocalNumber(context)); - } - - return numberList; - } - - public CharSequence phoneTypeToString(Context mContext, int type, CharSequence label) { - return label; - } - - public static class NumberData implements Parcelable { - - public static final Creator CREATOR = new Creator() { - public NumberData createFromParcel(Parcel in) { - return new NumberData(in); - } - - public NumberData[] newArray(int size) { - return new NumberData[size]; - } - }; - - public final String number; - public final String type; - - public NumberData(String type, String number) { - this.type = type; - this.number = number; - } - - public NumberData(Parcel in) { - number = in.readString(); - type = in.readString(); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(number); - dest.writeString(type); - } - } - - public static class ContactData implements Parcelable { - - public static final Creator CREATOR = new Creator() { - public ContactData createFromParcel(Parcel in) { - return new ContactData(in); - } - - public ContactData[] newArray(int size) { - return new ContactData[size]; - } - }; - - public final long id; - public final String name; - public final List numbers; - - public ContactData(long id, String name) { - this.id = id; - this.name = name; - this.numbers = new LinkedList(); - } - - public ContactData(Parcel in) { - id = in.readLong(); - name = in.readString(); - numbers = new LinkedList(); - in.readTypedList(numbers, NumberData.CREATOR); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(id); - dest.writeString(name); - dest.writeTypedList(numbers); - } - } - -} diff --git a/libsession/src/main/java/org/session/libsession/messaging/contacts/ContactsCursorLoader.java b/libsession/src/main/java/org/session/libsession/messaging/contacts/ContactsCursorLoader.java deleted file mode 100644 index 9d114ce04a..0000000000 --- a/libsession/src/main/java/org/session/libsession/messaging/contacts/ContactsCursorLoader.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2013-2017 Open Whisper Systems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.session.libsession.messaging.contacts; - -import android.content.Context; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.database.MergeCursor; -import android.provider.ContactsContract; -import android.text.TextUtils; - -import androidx.annotation.NonNull; -import androidx.loader.content.CursorLoader; - -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.GroupDatabase; -import org.thoughtcrime.securesms.database.ThreadDatabase; -import org.thoughtcrime.securesms.database.model.ThreadRecord; -import org.thoughtcrime.securesms.util.NumberUtil; - -import java.util.ArrayList; -import java.util.List; - -import network.loki.messenger.R; - -/** - * CursorLoader that initializes a ContactsDatabase instance - * - * @author Jake McGinty - */ -public class ContactsCursorLoader extends CursorLoader { - private static final String TAG = ContactsCursorLoader.class.getSimpleName(); - - static final int NORMAL_TYPE = 0; - static final int PUSH_TYPE = 1; - static final int NEW_TYPE = 2; - static final int RECENT_TYPE = 3; - static final int DIVIDER_TYPE = 4; - - static final String CONTACT_TYPE_COLUMN = "contact_type"; - static final String LABEL_COLUMN = "label"; - static final String NUMBER_TYPE_COLUMN = "number_type"; - static final String NUMBER_COLUMN = "number"; - static final String NAME_COLUMN = "name"; - - public static final class DisplayMode { - public static final int FLAG_PUSH = 1; - public static final int FLAG_SMS = 1 << 1; - public static final int FLAG_GROUPS = 1 << 2; - public static final int FLAG_ALL = FLAG_PUSH | FLAG_SMS | FLAG_GROUPS; - } - - private static final String[] CONTACT_PROJECTION = new String[]{NAME_COLUMN, - NUMBER_COLUMN, - NUMBER_TYPE_COLUMN, - LABEL_COLUMN, - CONTACT_TYPE_COLUMN}; - - private static final int RECENT_CONVERSATION_MAX = 25; - - private final String filter; - private final int mode; - private final boolean recents; - - public ContactsCursorLoader(@NonNull Context context, int mode, String filter, boolean recents) - { - super(context); - - this.filter = filter; - this.mode = mode; - this.recents = recents; - } - - @Override - public Cursor loadInBackground() { - List cursorList = TextUtils.isEmpty(filter) ? getUnfilteredResults() - : getFilteredResults(); - if (cursorList.size() > 0) { - return new MergeCursor(cursorList.toArray(new Cursor[0])); - } - return null; - } - - private List getUnfilteredResults() { - ArrayList cursorList = new ArrayList<>(); - - if (recents) { - Cursor recentConversations = getRecentConversationsCursor(); - if (recentConversations.getCount() > 0) { - cursorList.add(getRecentsHeaderCursor()); - cursorList.add(recentConversations); - cursorList.add(getContactsHeaderCursor()); - } - } - cursorList.addAll(getContactsCursors()); - return cursorList; - } - - private List getFilteredResults() { - ArrayList cursorList = new ArrayList<>(); - - if (groupsEnabled(mode)) { - Cursor groups = getGroupsCursor(); - if (groups.getCount() > 0) { - List contacts = getContactsCursors(); - if (!isCursorListEmpty(contacts)) { - cursorList.add(getContactsHeaderCursor()); - cursorList.addAll(contacts); - cursorList.add(getGroupsHeaderCursor()); - } - cursorList.add(groups); - } else { - cursorList.addAll(getContactsCursors()); - } - } else { - cursorList.addAll(getContactsCursors()); - } - - if (NumberUtil.isValidSmsOrEmail(filter)) { - cursorList.add(getNewNumberCursor()); - } - - return cursorList; - } - - private Cursor getRecentsHeaderCursor() { - MatrixCursor recentsHeader = new MatrixCursor(CONTACT_PROJECTION); - /* - recentsHeader.addRow(new Object[]{ getContext().getString(R.string.ContactsCursorLoader_recent_chats), - "", - ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, - "", - ContactsDatabase.DIVIDER_TYPE }); - */ - return recentsHeader; - } - - private Cursor getContactsHeaderCursor() { - MatrixCursor contactsHeader = new MatrixCursor(CONTACT_PROJECTION, 1); - /* - contactsHeader.addRow(new Object[] { getContext().getString(R.string.ContactsCursorLoader_contacts), - "", - ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, - "", - ContactsDatabase.DIVIDER_TYPE }); - */ - return contactsHeader; - } - - private Cursor getGroupsHeaderCursor() { - MatrixCursor groupHeader = new MatrixCursor(CONTACT_PROJECTION, 1); - groupHeader.addRow(new Object[]{ getContext().getString(R.string.ContactsCursorLoader_groups), - "", - ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, - "", - DIVIDER_TYPE }); - return groupHeader; - } - - - private Cursor getRecentConversationsCursor() { - ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(getContext()); - - MatrixCursor recentConversations = new MatrixCursor(CONTACT_PROJECTION, RECENT_CONVERSATION_MAX); - try (Cursor rawConversations = threadDatabase.getRecentConversationList(RECENT_CONVERSATION_MAX)) { - ThreadDatabase.Reader reader = threadDatabase.readerFor(rawConversations); - ThreadRecord threadRecord; - while ((threadRecord = reader.getNext()) != null) { - recentConversations.addRow(new Object[] { threadRecord.getRecipient().toShortString(), - threadRecord.getRecipient().getAddress().serialize(), - ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, - "", - RECENT_TYPE }); - } - } - return recentConversations; - } - - private List getContactsCursors() { - return new ArrayList<>(2); - /* - if (!Permissions.hasAny(getContext(), Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)) { - return cursorList; - } - - if (pushEnabled(mode)) { - cursorList.add(contactsDatabase.queryTextSecureContacts(filter)); - } - - if (pushEnabled(mode) && smsEnabled(mode)) { - cursorList.add(contactsDatabase.querySystemContacts(filter)); - } else if (smsEnabled(mode)) { - cursorList.add(filterNonPushContacts(contactsDatabase.querySystemContacts(filter))); - } - return cursorList; - */ - } - - private Cursor getGroupsCursor() { - MatrixCursor groupContacts = new MatrixCursor(CONTACT_PROJECTION); - try (GroupDatabase.Reader reader = DatabaseFactory.getGroupDatabase(getContext()).getGroupsFilteredByTitle(filter)) { - GroupDatabase.GroupRecord groupRecord; - while ((groupRecord = reader.getNext()) != null) { - groupContacts.addRow(new Object[] { groupRecord.getTitle(), - groupRecord.getEncodedId(), - ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM, - "", - NORMAL_TYPE }); - } - } - return groupContacts; - } - - private Cursor getNewNumberCursor() { - MatrixCursor newNumberCursor = new MatrixCursor(CONTACT_PROJECTION, 1); - newNumberCursor.addRow(new Object[] { getContext().getString(R.string.contact_selection_list__unknown_contact), - filter, - ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM, - "\u21e2", - NEW_TYPE }); - return newNumberCursor; - } - - private static boolean isCursorListEmpty(List list) { - int sum = 0; - for (Cursor cursor : list) { - sum += cursor.getCount(); - } - return sum == 0; - } - - private static boolean pushEnabled(int mode) { - return (mode & DisplayMode.FLAG_PUSH) > 0; - } - - private static boolean smsEnabled(int mode) { - return (mode & DisplayMode.FLAG_SMS) > 0; - } - - private static boolean groupsEnabled(int mode) { - return (mode & DisplayMode.FLAG_GROUPS) > 0; - } -} diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/OpenGroupPoller.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/OpenGroupPoller.kt index 1bd49b1cf1..4a51a28d80 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/OpenGroupPoller.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/OpenGroupPoller.kt @@ -161,6 +161,8 @@ class OpenGroupPoller(private val openGroup: OpenGroup) { if (quote.quotedMessageBody != quote.quotedMessageTimestamp.toString()) { quoteProto.setText(quote.quotedMessageBody) } dataMessageProto.setQuote(quoteProto.build()) } + val messageServerID = message.serverID + /* TODO: the signal service proto needs to be synced with iOS // Profile val profileProto = DataMessage.LokiProfile.newBuilder() profileProto.setDisplayName(message.displayName) @@ -171,12 +173,12 @@ class OpenGroupPoller(private val openGroup: OpenGroup) { } dataMessageProto.setProfile(profileProto.build()) // Open group info - val messageServerID = message.serverID if (messageServerID != null) { val openGroupProto = PublicChatInfo.newBuilder() openGroupProto.setServerID(messageServerID) dataMessageProto.setPublicChatInfo(openGroupProto.build()) } + */ // Signal group context val groupProto = GroupContext.newBuilder() groupProto.setId(ByteString.copyFrom(id))