Merge pull request #646 from oxen-io/cleanup

Cleanup
This commit is contained in:
Niels Andriesse 2021-07-09 13:59:04 +10:00 committed by GitHub
commit e7843e3af9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
155 changed files with 339 additions and 1769 deletions

View File

@ -93,80 +93,80 @@
android:value="false" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.LandingActivity"
android:name="org.thoughtcrime.securesms.onboarding.LandingActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.RegisterActivity"
android:name="org.thoughtcrime.securesms.onboarding.RegisterActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.RecoveryPhraseRestoreActivity"
android:name="org.thoughtcrime.securesms.onboarding.RecoveryPhraseRestoreActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.LinkDeviceActivity"
android:name="org.thoughtcrime.securesms.onboarding.LinkDeviceActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.DisplayNameActivity"
android:name="org.thoughtcrime.securesms.onboarding.DisplayNameActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.PNModeActivity"
android:name="org.thoughtcrime.securesms.onboarding.PNModeActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.HomeActivity"
android:name="org.thoughtcrime.securesms.home.HomeActivity"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:theme="@style/Theme.Session.DayNight.NoActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.SettingsActivity"
android:name="org.thoughtcrime.securesms.preferences.SettingsActivity"
android:screenOrientation="portrait"
android:label="@string/activity_settings_title" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.PathActivity"
android:name="org.thoughtcrime.securesms.home.PathActivity"
android:screenOrientation="portrait" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.QRCodeActivity"
android:name="org.thoughtcrime.securesms.preferences.QRCodeActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.CreatePrivateChatActivity"
android:name="org.thoughtcrime.securesms.dms.CreatePrivateChatActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.CreateClosedGroupActivity"
android:name="org.thoughtcrime.securesms.groups.CreateClosedGroupActivity"
android:screenOrientation="portrait" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.EditClosedGroupActivity"
android:name="org.thoughtcrime.securesms.groups.EditClosedGroupActivity"
android:label="@string/activity_edit_closed_group_title"
android:screenOrientation="portrait" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.JoinPublicChatActivity"
android:name="org.thoughtcrime.securesms.groups.JoinPublicChatActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.SeedActivity"
android:name="org.thoughtcrime.securesms.onboarding.SeedActivity"
android:screenOrientation="portrait" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.SelectContactsActivity"
android:name="org.thoughtcrime.securesms.contacts.SelectContactsActivity"
android:screenOrientation="portrait" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.PrivacySettingsActivity"
android:name="org.thoughtcrime.securesms.preferences.PrivacySettingsActivity"
android:label="@string/activity_privacy_settings_title"
android:screenOrientation="portrait" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.NotificationSettingsActivity"
android:name="org.thoughtcrime.securesms.preferences.NotificationSettingsActivity"
android:screenOrientation="portrait" />
<activity
android:name="org.thoughtcrime.securesms.loki.activities.ChatSettingsActivity"
android:name="org.thoughtcrime.securesms.preferences.ChatSettingsActivity"
android:screenOrientation="portrait" />
<activity
@ -198,7 +198,7 @@
<activity-alias
android:name=".RoutingActivity"
android:exported="true"
android:targetActivity="org.thoughtcrime.securesms.loki.activities.HomeActivity">
android:targetActivity="org.thoughtcrime.securesms.home.HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@ -215,14 +215,14 @@
<activity
android:name="org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2"
android:screenOrientation="portrait"
android:parentActivityName="org.thoughtcrime.securesms.loki.activities.HomeActivity"
android:parentActivityName="org.thoughtcrime.securesms.home.HomeActivity"
android:theme="@style/Theme.Session.DayNight.FlatActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.thoughtcrime.securesms.loki.activities.HomeActivity" />
android:value="org.thoughtcrime.securesms.home.HomeActivity" />
</activity>
<activity
android:name="org.thoughtcrime.securesms.loki.activities.OpenGroupGuidelinesActivity"
android:name="org.thoughtcrime.securesms.groups.OpenGroupGuidelinesActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.TextSecure.DayNight" />
<activity
@ -291,7 +291,7 @@
android:exported="true"
android:theme="@style/Theme.Session.DayNight.NoActionBar" />
<service
android:name="org.thoughtcrime.securesms.loki.api.PushNotificationService"
android:name="org.thoughtcrime.securesms.notifications.PushNotificationService"
android:enabled="true"
android:exported="false">
<intent-filter>
@ -411,7 +411,7 @@
</intent-filter>
</receiver>
<receiver
android:name="org.thoughtcrime.securesms.loki.api.BackgroundPollWorker$BootBroadcastReceiver"
android:name="org.thoughtcrime.securesms.notifications.BackgroundPollWorker$BootBroadcastReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />

View File

@ -31,7 +31,6 @@ import androidx.multidex.MultiDexApplication;
import org.conscrypt.Conscrypt;
import org.session.libsession.avatars.AvatarHelper;
import org.session.libsession.messaging.MessagingModuleConfiguration;
import org.session.libsession.messaging.contacts.Contact;
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2;
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
@ -43,7 +42,6 @@ import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
import org.session.libsession.utilities.dynamiclanguage.LocaleParser;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.ThreadUtils;
import org.signal.aesgcmprovider.AesGcmProvider;
@ -60,17 +58,14 @@ import org.thoughtcrime.securesms.jobs.JobManagerFactories;
import org.thoughtcrime.securesms.logging.AndroidLogger;
import org.thoughtcrime.securesms.logging.PersistentLogger;
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker;
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities;
import org.thoughtcrime.securesms.loki.utilities.FcmUtils;
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.thoughtcrime.securesms.notifications.BackgroundPollWorker;
import org.thoughtcrime.securesms.notifications.LokiPushNotificationManager;
import org.thoughtcrime.securesms.groups.OpenGroupManager;
import org.thoughtcrime.securesms.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.util.Broadcaster;
import org.thoughtcrime.securesms.notifications.FcmUtils;
import org.thoughtcrime.securesms.util.UiModeUtilities;
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;

View File

@ -10,7 +10,7 @@ import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.loki.views.UserView;
import org.thoughtcrime.securesms.contacts.UserView;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.Conversions;

View File

@ -12,8 +12,8 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
import org.thoughtcrime.securesms.loki.activities.LandingActivity;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.thoughtcrime.securesms.onboarding.LandingActivity;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.session.libsession.utilities.TextSecurePreferences;

View File

@ -42,9 +42,8 @@ import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListFragment;
import org.thoughtcrime.securesms.loki.fragments.ContactSelectionListLoader.DisplayMode;
import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.contacts.ContactSelectionListFragment;
import org.thoughtcrime.securesms.contacts.ContactSelectionListLoader.DisplayMode;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.session.libsession.utilities.recipients.Recipient;
@ -54,7 +53,6 @@ import org.session.libsession.utilities.ViewUtil;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import network.loki.messenger.R;

View File

@ -11,7 +11,7 @@ import androidx.appcompat.app.AppCompatActivity;
import android.widget.Toast;
import org.session.libsession.utilities.Address;
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.util.CommunicationActions;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.backup;
import android.app.Activity
import android.app.Application
@ -9,17 +9,13 @@ import android.os.Bundle
import android.provider.OpenableColumns
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.StyleSpan
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.widget.addTextChangedListener
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
@ -28,18 +24,17 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import network.loki.messenger.R
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.backup.FullBackupImporter
import org.thoughtcrime.securesms.backup.FullBackupImporter.DatabaseDowngradeException
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.loki.utilities.show
import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.util.show
import org.thoughtcrime.securesms.notifications.NotificationChannels
import org.thoughtcrime.securesms.util.BackupUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.home.HomeActivity
class BackupRestoreActivity : BaseActionBarActivity() {

View File

@ -21,8 +21,7 @@ import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream
import org.thoughtcrime.securesms.database.*
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase
import org.thoughtcrime.securesms.database.LokiBackupFilesDatabase
import org.thoughtcrime.securesms.util.BackupUtil
import org.session.libsession.utilities.Util
import org.session.libsignal.crypto.kdf.HKDFv3

View File

@ -19,7 +19,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.thoughtcrime.securesms.loki.utilities.AvatarPlaceholderGenerator;
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.components
import android.content.Context
import android.graphics.Canvas
@ -9,7 +9,7 @@ import android.view.LayoutInflater
import android.widget.RelativeLayout
import kotlinx.android.synthetic.main.view_separator.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.toPx
import org.session.libsession.utilities.ThemeUtil
class LabeledSeparatorView : RelativeLayout {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.components
import android.content.Context
import android.util.AttributeSet
@ -17,7 +17,7 @@ import org.session.libsession.utilities.Address
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.utilities.AvatarPlaceholderGenerator
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator
import org.thoughtcrime.securesms.mms.GlideRequests
class ProfilePictureView : RelativeLayout {

View File

@ -22,8 +22,8 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.session.libsession.messaging.contacts.Contact;
import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
import org.thoughtcrime.securesms.database.SessionContactDatabase;
import org.thoughtcrime.securesms.util.UiModeUtilities;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.mms.Slide;

View File

@ -8,7 +8,7 @@ import org.session.libsession.messaging.messages.control.TypingIndicator;
import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.Util;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.fragments
package org.thoughtcrime.securesms.contacts
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
@ -7,7 +7,7 @@ import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.contact_selection_list_divider.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.views.UserView
import org.thoughtcrime.securesms.contacts.UserView
import org.thoughtcrime.securesms.mms.GlideRequests
import org.session.libsession.utilities.recipients.Recipient

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.fragments
package org.thoughtcrime.securesms.contacts
import android.os.Bundle
import androidx.fragment.app.Fragment
@ -11,10 +11,11 @@ import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.contact_selection_list_fragment.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.mms.GlideApp
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.contacts.ContactSelectionListItem
import org.thoughtcrime.securesms.contacts.ContactSelectionListLoader
class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<List<ContactSelectionListItem>>, ContactClickListener {
private var cursorFilter: String? = null
@ -98,7 +99,7 @@ class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<L
update(listOf())
}
private fun update(items: List<ContactSelectionListItem>) {
private fun update(items: List<ContactSelectionListItem>) {
if (activity?.isDestroyed == true) {
Log.e(ContactSelectionListFragment::class.java.name,
"Received a loader callback after the fragment was detached from the activity.",

View File

@ -1,8 +1,8 @@
package org.thoughtcrime.securesms.loki.fragments
package org.thoughtcrime.securesms.contacts
import android.content.Context
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities
import org.thoughtcrime.securesms.util.ContactUtilities
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.util.AsyncLoader

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.contacts
import android.app.Activity
import android.content.Intent
@ -40,8 +40,8 @@ class SelectContactsActivity : PassphraseRequiredActionBarActivity(), LoaderMana
setContentView(R.layout.activity_select_contacts)
supportActionBar!!.title = resources.getString(R.string.activity_select_contacts_title)
usersToExclude = intent.getStringArrayExtra(Companion.usersToExcludeKey)?.toSet() ?: setOf()
val emptyStateText = intent.getStringExtra(Companion.emptyStateTextKey)
usersToExclude = intent.getStringArrayExtra(usersToExcludeKey)?.toSet() ?: setOf()
val emptyStateText = intent.getStringExtra(emptyStateTextKey)
if (emptyStateText != null) {
emptyStateMessageTextView.text = emptyStateText
}

View File

@ -1,10 +1,9 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.contacts
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.view.ViewGroup
import org.session.libsession.utilities.Address
import org.thoughtcrime.securesms.loki.views.UserView
import org.thoughtcrime.securesms.mms.GlideRequests
import org.session.libsession.utilities.recipients.Recipient

View File

@ -1,7 +1,7 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.contacts
import android.content.Context
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities
import org.thoughtcrime.securesms.util.ContactUtilities
import org.thoughtcrime.securesms.util.AsyncLoader
class SelectContactsLoader(context: Context, val usersToExclude: Set<String>) : AsyncLoader<List<String>>(context) {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.contacts
import android.content.Context
import android.util.AttributeSet
@ -10,7 +10,7 @@ import kotlinx.android.synthetic.main.view_user.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
import org.thoughtcrime.securesms.mms.GlideRequests
import org.session.libsession.utilities.recipients.Recipient

View File

@ -72,7 +72,6 @@ import org.session.libsession.utilities.concurrent.SimpleTask
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.recipients.RecipientModifiedListener
import org.session.libsignal.utilities.ListenableFuture
import org.session.libsignal.utilities.SettableFuture
import org.session.libsignal.utilities.guava.Optional
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
@ -101,20 +100,16 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel.LinkPreviewState
import org.thoughtcrime.securesms.loki.activities.SelectContactsActivity
import org.thoughtcrime.securesms.loki.activities.SelectContactsActivity.Companion.selectedContactsKey
import org.thoughtcrime.securesms.loki.utilities.ActivityDispatcher
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities
import org.thoughtcrime.securesms.loki.utilities.push
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
import org.thoughtcrime.securesms.contacts.SelectContactsActivity.Companion.selectedContactsKey
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
import org.thoughtcrime.securesms.util.toPx
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.mediasend.MediaSendActivity
import org.thoughtcrime.securesms.mms.*
import org.thoughtcrime.securesms.notifications.MarkReadReceiver
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.SaveAttachmentTask
import org.thoughtcrime.securesms.util.*
import java.util.*
import java.util.concurrent.ExecutionException
import kotlin.math.*

View File

@ -8,8 +8,8 @@ import android.view.VelocityTracker
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_conversation_v2.*
import org.thoughtcrime.securesms.loki.utilities.disableClipping
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.disableClipping
import org.thoughtcrime.securesms.util.toPx
import kotlin.math.abs
import kotlin.math.max

View File

@ -19,7 +19,7 @@ import org.thoughtcrime.securesms.MediaPreviewActivity
import org.thoughtcrime.securesms.components.CornerMask
import org.thoughtcrime.securesms.conversation.v2.utilities.KThumbnailView
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.loki.utilities.ActivityDispatcher
import org.thoughtcrime.securesms.util.ActivityDispatcher
import org.thoughtcrime.securesms.longmessage.LongMessageActivity
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.Slide

View File

@ -8,7 +8,7 @@ import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.view_link_preview_draft.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.toPx
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.ImageSlide

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.conversation.v2.components
import android.content.Context
import android.util.AttributeSet
@ -8,7 +8,7 @@ import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ListView
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.toPx
import org.thoughtcrime.securesms.mms.GlideRequests
import org.session.libsession.messaging.mentions.Mention

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.conversation.v2.components
import android.content.Context
import android.util.AttributeSet

View File

@ -8,8 +8,8 @@ import android.widget.FrameLayout
import kotlinx.android.synthetic.main.view_open_group_guidelines.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.loki.activities.OpenGroupGuidelinesActivity
import org.thoughtcrime.securesms.loki.utilities.push
import org.thoughtcrime.securesms.groups.OpenGroupGuidelinesActivity
import org.thoughtcrime.securesms.util.push
class OpenGroupGuidelinesView : FrameLayout {

View File

@ -9,12 +9,11 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.dialog_join_open_group.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.open_groups.OpenGroupV2
import org.session.libsession.utilities.OpenGroupUrlParser
import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
import org.thoughtcrime.securesms.loki.api.OpenGroupManager
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
/** Shown upon tapping an open group invitation. */
class JoinOpenGroupDialog(private val name: String, private val url: String) : BaseDialog() {
@ -38,7 +37,7 @@ class JoinOpenGroupDialog(private val name: String, private val url: String) : B
val activity = requireContext() as AppCompatActivity
ThreadUtils.queue {
OpenGroupManager.add(openGroup.server, openGroup.room, openGroup.serverPublicKey, activity)
MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(activity)
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(activity)
}
dismiss()
}

View File

@ -19,8 +19,8 @@ import org.thoughtcrime.securesms.conversation.v2.messages.QuoteView
import org.thoughtcrime.securesms.conversation.v2.messages.QuoteViewDelegate
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.loki.utilities.toDp
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.toDp
import org.thoughtcrime.securesms.util.toPx
import org.thoughtcrime.securesms.mms.GlideRequests
import kotlin.math.max
import kotlin.math.roundToInt

View File

@ -17,10 +17,9 @@ import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.annotation.DrawableRes
import network.loki.messenger.R
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageView
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.loki.views.GlowViewUtilities
import org.thoughtcrime.securesms.loki.views.InputBarButtonImageViewContainer
import org.thoughtcrime.securesms.util.*
import org.thoughtcrime.securesms.util.GlowViewUtilities
import org.thoughtcrime.securesms.util.InputBarButtonImageViewContainer
import java.util.*
import kotlin.math.abs

View File

@ -9,7 +9,7 @@ import android.util.Log
import android.widget.RelativeLayout
import androidx.appcompat.widget.AppCompatEditText
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.toPx
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt

View File

@ -13,9 +13,9 @@ import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.view_input_bar_recording.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.animateSizeChange
import org.thoughtcrime.securesms.loki.utilities.disableClipping
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.animateSizeChange
import org.thoughtcrime.securesms.util.disableClipping
import org.thoughtcrime.securesms.util.toPx
import org.thoughtcrime.securesms.util.DateUtils
import java.util.*

View File

@ -8,7 +8,7 @@ import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.ListView
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.toPx
import org.thoughtcrime.securesms.mms.GlideRequests
import org.session.libsession.messaging.mentions.Mention

View File

@ -31,6 +31,7 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p
if (selectedItems.isEmpty()) { return }
val firstMessage = selectedItems.iterator().next()
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getOpenGroupChat(threadID)
val thread = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)!!
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
fun userCanDeleteSelectedItems(): Boolean {
if (openGroup == null) { return true }
@ -54,7 +55,7 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p
menu.findItem(R.id.menu_context_copy).isVisible = !containsControlMessage && hasText
// Copy Session ID
menu.findItem(R.id.menu_context_copy_public_key).isVisible =
(openGroup != null && selectedItems.size == 1 && firstMessage.recipient.address.toString() != userPublicKey)
(thread.isGroupRecipient && selectedItems.size == 1 && firstMessage.recipient.address.toString() != userPublicKey)
// Resend
menu.findItem(R.id.menu_context_resend).isVisible = (selectedItems.size == 1 && firstMessage.isFailed)
// Save media

View File

@ -38,10 +38,10 @@ import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.*
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.activities.EditClosedGroupActivity
import org.thoughtcrime.securesms.loki.activities.EditClosedGroupActivity.Companion.groupIDKey
import org.thoughtcrime.securesms.loki.activities.SelectContactsActivity
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.groups.EditClosedGroupActivity
import org.thoughtcrime.securesms.groups.EditClosedGroupActivity.Companion.groupIDKey
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
import org.thoughtcrime.securesms.util.getColorWithID
import org.thoughtcrime.securesms.util.BitmapUtil
import java.io.IOException

View File

@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtiliti
import org.thoughtcrime.securesms.conversation.v2.utilities.ModalURLSpan
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities.getIntersectedModalSpans
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities
import org.thoughtcrime.securesms.util.UiModeUtilities
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.ImageSlide

View File

@ -1,11 +1,8 @@
package org.thoughtcrime.securesms.conversation.v2.messages
import android.content.ContentResolver
import android.content.Context
import android.content.res.ColorStateList
import android.content.res.Resources
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.widget.LinearLayout
import android.widget.RelativeLayout
@ -13,22 +10,19 @@ import androidx.annotation.ColorInt
import androidx.core.content.res.ResourcesCompat
import androidx.core.text.toSpannable
import androidx.core.view.isVisible
import androidx.core.view.marginStart
import com.google.android.exoplayer2.util.MimeTypes
import kotlinx.android.synthetic.main.view_link_preview.view.*
import kotlinx.android.synthetic.main.view_quote.view.*
import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.utilities.UpdateMessageData
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.util.*
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.ImageSlide
import org.thoughtcrime.securesms.mms.SlideDeck
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.UiModeUtilities
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt

View File

@ -6,7 +6,6 @@ import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import android.text.method.LinkMovementMethod
import android.text.style.URLSpan
import android.text.util.Linkify
import android.util.AttributeSet
@ -23,7 +22,6 @@ import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat
import androidx.core.text.getSpans
import androidx.core.text.toSpannable
import androidx.core.text.util.LinkifyCompat
import kotlinx.android.synthetic.main.view_link_preview.view.*
import kotlinx.android.synthetic.main.view_visible_message_content.view.*
import network.loki.messenger.R
@ -34,14 +32,16 @@ import org.thoughtcrime.securesms.conversation.v2.components.AlbumThumbnailView
import org.thoughtcrime.securesms.components.emoji.EmojiTextView
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.conversation.v2.dialogs.OpenURLDialog
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.ModalURLSpan
import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities.getIntersectedModalSpans
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.util.*
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.SearchUtil
import org.thoughtcrime.securesms.util.SearchUtil.StyleFactory
import org.thoughtcrime.securesms.util.UiModeUtilities
import java.util.*
import kotlin.math.roundToInt

View File

@ -24,12 +24,8 @@ import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.loki.utilities.disableClipping
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.loki.utilities.toDp
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.*
import java.util.*
import kotlin.math.abs
import kotlin.math.min

View File

@ -6,7 +6,7 @@ import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities
import org.thoughtcrime.securesms.util.UiModeUtilities
open class BaseDialog : DialogFragment() {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.utilities
package org.thoughtcrime.securesms.conversation.v2.utilities
import android.content.Context
import org.session.libsession.utilities.TextSecurePreferences

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.utilities
package org.thoughtcrime.securesms.conversation.v2.utilities
import android.content.Context
import android.graphics.Typeface
@ -13,6 +13,7 @@ import nl.komponents.kovenant.combine.Tuple2
import org.session.libsession.messaging.contacts.Contact
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.util.UiModeUtilities
import java.util.regex.Pattern
object MentionUtilities {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.utilities
package org.thoughtcrime.securesms.crypto
import android.content.Context

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.database
package org.thoughtcrime.securesms.database
import android.net.Uri
import java.util.*

View File

@ -25,13 +25,8 @@ import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
import org.thoughtcrime.securesms.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.database.SessionJobDatabase;
public class DatabaseFactory {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.utilities
package org.thoughtcrime.securesms.database
import android.content.ContentValues
import androidx.core.database.getStringOrNull

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.database
package org.thoughtcrime.securesms.database
import android.content.ContentValues
import android.content.Context
@ -9,9 +9,9 @@ import org.session.libsignal.crypto.ecc.ECKeyPair
import org.session.libsignal.database.LokiAPIDatabaseProtocol
import org.session.libsignal.utilities.*
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.*
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.util.*
import java.util.*
import kotlin.Array
import kotlin.Boolean

View File

@ -1,10 +1,9 @@
package org.thoughtcrime.securesms.loki.database
package org.thoughtcrime.securesms.database
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.net.Uri
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import java.lang.IllegalArgumentException
import java.util.*

View File

@ -1,14 +1,10 @@
package org.thoughtcrime.securesms.loki.database
package org.thoughtcrime.securesms.database
import android.content.ContentValues
import android.content.Context
import net.sqlcipher.database.SQLiteDatabase.CONFLICT_REPLACE
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.loki.utilities.*
import org.session.libsignal.database.LokiMessageDatabaseProtocol
import org.session.libsignal.utilities.Log
class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiMessageDatabaseProtocol {
@ -63,9 +59,9 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
val database = databaseHelper.writableDatabase
val serverID = database.get(messageIDTable,
"${Companion.messageID} = ? AND ${Companion.messageType} = ?",
"${Companion.messageID} = ? AND $messageType = ?",
arrayOf(messageID.toString(), (if (isSms) SMS_TYPE else MMS_TYPE).toString())) { cursor ->
cursor.getInt(Companion.serverID).toLong()
cursor.getInt(serverID).toLong()
} ?: return
database.beginTransaction()
@ -89,7 +85,7 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
return database.get(messageIDTable,
"$messageID = ? AND ${Companion.serverID} = ?",
arrayOf(mappedID.toString(), mappedServerID.toString())) { cursor ->
cursor.getInt(Companion.messageID).toLong() to (cursor.getInt(messageType) == SMS_TYPE)
cursor.getInt(messageID).toLong() to (cursor.getInt(messageType) == SMS_TYPE)
}
}
@ -137,18 +133,18 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
val database = databaseHelper.writableDatabase
try {
val messages = mutableSetOf<Pair<Long,Long>>()
database.get(messageThreadMappingTable, "${Companion.threadID} = ?", arrayOf(threadId.toString())) { cursor ->
database.get(messageThreadMappingTable, "$threadID = ?", arrayOf(threadId.toString())) { cursor ->
// for each add
while (cursor.moveToNext()) {
messages.add(cursor.getLong(Companion.messageID) to cursor.getLong(Companion.serverID))
messages.add(cursor.getLong(messageID) to cursor.getLong(serverID))
}
}
var deletedCount = 0L
database.beginTransaction()
messages.forEach { (messageId, serverId) ->
deletedCount += database.delete(messageIDTable, "${Companion.messageID} = ? AND ${Companion.serverID} = ?", arrayOf(messageId.toString(), serverId.toString()))
deletedCount += database.delete(messageIDTable, "$messageID = ? AND $serverID = ?", arrayOf(messageId.toString(), serverId.toString()))
}
val mappingDeleted = database.delete(messageThreadMappingTable, "${Companion.threadID} = ?", arrayOf(threadId.toString()))
val mappingDeleted = database.delete(messageThreadMappingTable, "$threadID = ?", arrayOf(threadId.toString()))
database.setTransactionSuccessful()
} finally {
database.endTransaction()

View File

@ -1,12 +1,9 @@
package org.thoughtcrime.securesms.loki.database
package org.thoughtcrime.securesms.database
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.loki.utilities.*
import org.session.libsession.messaging.open_groups.OpenGroupV2
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.recipients.Recipient

View File

@ -1,9 +1,7 @@
package org.thoughtcrime.securesms.loki.database
package org.thoughtcrime.securesms.database
import android.content.Context
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.loki.utilities.get
import org.session.libsession.utilities.TextSecurePreferences
class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {

View File

@ -1,13 +1,11 @@
package org.thoughtcrime.securesms.loki.database
package org.thoughtcrime.securesms.database
import android.content.ContentValues
import android.content.Context
import net.sqlcipher.Cursor
import org.session.libsession.messaging.contacts.Contact
import org.session.libsignal.utilities.Base64
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.loki.utilities.*
class SessionContactDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
@ -35,7 +33,7 @@ class SessionContactDatabase(context: Context, helper: SQLCipherOpenHelper) : Da
fun getContactWithSessionID(sessionID: String): Contact? {
val database = databaseHelper.readableDatabase
return database.get(sessionContactTable, "${SessionContactDatabase.sessionID} = ?", arrayOf( sessionID )) { cursor ->
return database.get(sessionContactTable, "${Companion.sessionID} = ?", arrayOf( sessionID )) { cursor ->
contactFromCursor(cursor)
}
}

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.database
package org.thoughtcrime.securesms.database
import android.content.ContentValues
import android.content.Context
@ -6,10 +6,10 @@ import net.sqlcipher.Cursor
import org.session.libsession.messaging.jobs.*
import org.session.libsession.messaging.utilities.Data
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.*
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.util.*
class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {

View File

@ -29,11 +29,8 @@ import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
import org.thoughtcrime.securesms.loki.api.OpenGroupManager
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol
import org.thoughtcrime.securesms.loki.utilities.get
import org.thoughtcrime.securesms.loki.utilities.getString
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.util.SessionMetaProtocol
import org.thoughtcrime.securesms.mms.PartAuthority
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {

View File

@ -49,7 +49,7 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;

View File

@ -23,14 +23,13 @@ import org.thoughtcrime.securesms.database.SearchDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
import org.thoughtcrime.securesms.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.database.LokiBackupFilesDatabase;
import org.thoughtcrime.securesms.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.database.LokiThreadDatabase;
import org.thoughtcrime.securesms.database.LokiUserDatabase;
import org.thoughtcrime.securesms.database.SessionContactDatabase;
import org.thoughtcrime.securesms.database.SessionJobDatabase;
public class SQLCipherOpenHelper extends SQLiteOpenHelper {
@ -182,8 +181,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
if (oldVersion < lokiV12) {
db.execSQL(LokiAPIDatabase.getCreateLastMessageHashValueTable2Command());
db.execSQL(ClosedGroupsMigration.getCreateCurrentClosedGroupRatchetTableCommand());
db.execSQL(ClosedGroupsMigration.getCreateClosedGroupPrivateKeyTableCommand());
}
if (oldVersion < lokiV13) {
@ -193,10 +190,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
if (oldVersion < lokiV14_BACKUP_FILES) {
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
}
if (oldVersion < lokiV15) {
db.execSQL(ClosedGroupsMigration.getCreateOldClosedGroupRatchetTableCommand());
}
if (oldVersion < lokiV16) {
db.execSQL(LokiAPIDatabase.getCreateOpenGroupProfilePictureTableCommand());
@ -217,7 +210,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
if (oldVersion < lokiV19) {
db.execSQL(LokiAPIDatabase.getCreateClosedGroupEncryptionKeyPairsTable());
db.execSQL(LokiAPIDatabase.getCreateClosedGroupPublicKeysTable());
ClosedGroupsMigration.INSTANCE.perform(db);
db.execSQL("DROP TABLE identities");
deleteJobRecords(db, "RetrieveProfileJob");
deleteJobRecords(db,

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.dms
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
@ -32,8 +32,8 @@ import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragmentDelegate
import org.thoughtcrime.securesms.util.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.util.ScanQRCodeWrapperFragmentDelegate
class CreatePrivateChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
private val adapter = CreatePrivateChatActivityAdapter(this)

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.dialogs
package org.thoughtcrime.securesms.groups
import android.os.Bundle
import com.google.android.material.bottomsheet.BottomSheetDialogFragment

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.groups
import android.content.Context
import android.content.Intent
@ -19,14 +19,15 @@ import org.session.libsession.messaging.sending_receiving.groupSizeLimit
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.DistributionTypes
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.utilities.fadeIn
import org.thoughtcrime.securesms.loki.utilities.fadeOut
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
import org.thoughtcrime.securesms.mms.GlideApp
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.contacts.SelectContactsAdapter
import org.thoughtcrime.securesms.contacts.SelectContactsLoader
//TODO Refactor to avoid using kotlinx.android.synthetic
class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderManager.LoaderCallbacks<List<String>> {

View File

@ -1,10 +1,11 @@
package org.thoughtcrime.securesms.loki.viewmodel
package org.thoughtcrime.securesms.groups
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
import org.thoughtcrime.securesms.util.State
typealias DefaultGroups = List<OpenGroupAPIV2.DefaultGroup>
typealias GroupState = State<DefaultGroups>

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.groups
import android.content.Context
import android.content.Intent
@ -24,15 +24,15 @@ import org.session.libsession.messaging.sending_receiving.groupSizeLimit
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.session.libsession.utilities.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.loki.dialogs.ClosedGroupEditingOptionsBottomSheet
import org.thoughtcrime.securesms.loki.utilities.fadeIn
import org.thoughtcrime.securesms.loki.utilities.fadeOut
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
import org.thoughtcrime.securesms.mms.GlideApp
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.ThemeUtil
import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
import java.io.IOException
class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.groups
import android.content.Context
import org.thoughtcrime.securesms.database.DatabaseFactory

View File

@ -1,10 +1,10 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.groups
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.view.ViewGroup
import org.session.libsession.utilities.Address
import org.thoughtcrime.securesms.loki.views.UserView
import org.thoughtcrime.securesms.contacts.UserView
import org.thoughtcrime.securesms.mms.GlideRequests
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.TextSecurePreferences

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.groups
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
@ -25,22 +25,20 @@ import network.loki.messenger.R
import okhttp3.HttpUrl
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2.DefaultGroup
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.DistributionTypes
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.GroupUtil
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.PublicKeyValidation
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.groups.DefaultGroupsViewModel
import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.loki.api.OpenGroupManager
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.loki.fragments.ScanQRCodeWrapperFragmentDelegate
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
import org.thoughtcrime.securesms.loki.viewmodel.DefaultGroupsViewModel
import org.thoughtcrime.securesms.loki.viewmodel.State
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.util.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.util.ScanQRCodeWrapperFragmentDelegate
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import org.thoughtcrime.securesms.util.State
import java.util.*
class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
@ -108,7 +106,7 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
} else {
throw Exception("No longer supported.")
}
MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(this@JoinPublicChatActivity)
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@JoinPublicChatActivity)
withContext(Dispatchers.Main) {
val recipient = Recipient.from(this@JoinPublicChatActivity, Address.fromSerialized(groupID), false)
openConversationActivity(this@JoinPublicChatActivity, threadID, recipient)

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.groups
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_open_group_guidelines.*

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.api
package org.thoughtcrime.securesms.groups
import android.content.Context
import android.graphics.Bitmap
@ -11,7 +11,6 @@ import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPolle
import org.session.libsession.utilities.Util
import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.util.BitmapUtil
import java.util.concurrent.Executors

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.utilities
package org.thoughtcrime.securesms.groups
import android.content.Context
import androidx.annotation.WorkerThread

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.dialogs
package org.thoughtcrime.securesms.home
import android.os.Bundle
import com.google.android.material.bottomsheet.BottomSheetDialogFragment

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.home
import android.content.Context
import android.content.res.Resources
@ -15,8 +15,8 @@ import kotlinx.android.synthetic.main.view_conversation.view.*
import network.loki.messenger.R
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities.highlightMentions
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities.highlightMentions
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.DateUtils
import java.util.*

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.home
import android.app.AlertDialog
import android.content.BroadcastReceiver
@ -11,7 +11,6 @@ import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.util.DisplayMetrics
import android.util.Log
import android.view.View
import android.widget.RelativeLayout
import android.widget.Toast
@ -32,6 +31,7 @@ import org.greenrobot.eventbus.ThreadMode
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.utilities.*
import org.session.libsession.utilities.Util
import org.session.libsignal.utilities.ThreadUtils
import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.ApplicationContext
@ -40,19 +40,20 @@ import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.loki.api.OpenGroupManager
import org.thoughtcrime.securesms.loki.dialogs.*
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.loki.views.ConversationView
import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegate
import org.thoughtcrime.securesms.loki.views.SeedReminderViewDelegate
import org.thoughtcrime.securesms.dms.CreatePrivateChatActivity
import org.thoughtcrime.securesms.groups.CreateClosedGroupActivity
import org.thoughtcrime.securesms.groups.JoinPublicChatActivity
import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import org.thoughtcrime.securesms.util.*
import org.thoughtcrime.securesms.onboarding.SeedReminderViewDelegate
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.onboarding.SeedActivity
import org.thoughtcrime.securesms.preferences.SettingsActivity
import org.thoughtcrime.securesms.util.IP2Country
import java.io.IOException
import java.util.*
import java.util.concurrent.TimeUnit
class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
private lateinit var glide: GlideRequests
@ -168,7 +169,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
}
if (TextSecurePreferences.getConfigurationMessageSynced(this)) {
lifecycleScope.launch(Dispatchers.IO) {
MultiDeviceProtocol.syncConfigurationIfNeeded(this@HomeActivity)
ConfigurationMessageUtilities.syncConfigurationIfNeeded(this@HomeActivity)
}
}
}

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.home
import android.content.Context
import android.database.Cursor
@ -7,7 +7,6 @@ import android.view.ViewGroup
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.loki.views.ConversationView
import org.thoughtcrime.securesms.mms.GlideRequests
class HomeAdapter(context: Context, cursor: Cursor) : CursorRecyclerViewAdapter<HomeAdapter.ViewHolder>(context, cursor) {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.home
import android.content.Context
import android.database.Cursor

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.home
import android.animation.FloatEvaluator
import android.animation.PointFEvaluator
@ -16,7 +16,9 @@ import android.widget.RelativeLayout
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.util.*
import org.thoughtcrime.securesms.util.GlowViewUtilities
import org.thoughtcrime.securesms.util.NewConversationButtonImageView
class NewConversationButtonSetView : RelativeLayout {
private var expandedButton: Button? = null

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.home
import android.content.BroadcastReceiver
import android.content.Context
@ -22,9 +22,10 @@ import network.loki.messenger.R
import org.session.libsession.snode.OnionRequestAPI
import org.session.libsignal.utilities.Snode
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.loki.utilities.*
import org.thoughtcrime.securesms.loki.views.GlowViewUtilities
import org.thoughtcrime.securesms.loki.views.PathDotView
import org.thoughtcrime.securesms.util.*
import org.thoughtcrime.securesms.util.GlowViewUtilities
import org.thoughtcrime.securesms.util.IP2Country
import org.thoughtcrime.securesms.util.PathDotView
class PathActivity : PassphraseRequiredActionBarActivity() {
private val broadcastReceivers = mutableListOf<BroadcastReceiver>()

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.home
import android.content.BroadcastReceiver
import android.content.Context
@ -12,8 +12,8 @@ import android.view.View
import androidx.annotation.ColorInt
import network.loki.messenger.R
import org.session.libsession.snode.OnionRequestAPI
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.loki.utilities.toPx
import org.thoughtcrime.securesms.util.getColorWithID
import org.thoughtcrime.securesms.util.toPx
class PathStatusView : View {
private val broadcastReceivers = mutableListOf<BroadcastReceiver>()

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.dialogs
package org.thoughtcrime.securesms.home
import android.annotation.SuppressLint
import android.content.ClipData
@ -17,7 +17,6 @@ import network.loki.messenger.R
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.SSKEnvironment
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.mms.GlideApp

View File

@ -14,7 +14,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
import org.thoughtcrime.securesms.loki.api.PrepareAttachmentAudioExtrasJob;
import java.util.ArrayList;
import java.util.Arrays;

View File

@ -6,7 +6,7 @@ import org.session.libsession.messaging.utilities.Data;
import org.session.libsignal.utilities.NoExternalStorageException;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.loki.database.BackupFileRecord;
import org.thoughtcrime.securesms.database.BackupFileRecord;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.service.GenericForegroundService;
import org.thoughtcrime.securesms.util.BackupUtil;

View File

@ -1,9 +1,7 @@
package org.thoughtcrime.securesms.loki.api
package org.thoughtcrime.securesms.jobs
import android.media.MediaDataSource
import android.os.Build
import org.session.libsignal.utilities.Log
import androidx.annotation.RequiresApi
import org.greenrobot.eventbus.EventBus
import org.session.libsession.messaging.utilities.Data
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
@ -13,9 +11,7 @@ import org.session.libsession.utilities.DecodedAudio
import org.session.libsession.utilities.InputStreamMediaDataSource
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobs.BaseJob
import org.thoughtcrime.securesms.mms.PartAuthority
import java.io.InputStream
import java.lang.IllegalStateException
import java.util.*
import java.util.concurrent.TimeUnit

View File

@ -1,71 +0,0 @@
package org.thoughtcrime.securesms.loki.api
import android.content.Context
import androidx.work.*
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
/**
* Delegates the [OpenGroupUtilities.updateGroupInfo] call to the work manager.
*/
class PublicChatInfoUpdateWorker(val context: Context, params: WorkerParameters) : Worker(context, params) {
companion object {
const val TAG = "PublicChatInfoUpdateWorker"
private const val DATA_KEY_SERVER_URL = "server_uRL"
private const val DATA_KEY_CHANNEL = "channel"
private const val DATA_KEY_ROOM = "room"
@JvmStatic
fun scheduleInstant(context: Context, serverUrl: String, room :String) {
val workRequest = OneTimeWorkRequestBuilder<PublicChatInfoUpdateWorker>()
.setConstraints(Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
.setInputData(workDataOf(
DATA_KEY_SERVER_URL to serverUrl,
DATA_KEY_ROOM to room
))
.build()
WorkManager
.getInstance(context)
.enqueue(workRequest)
}
@JvmStatic
fun scheduleInstant(context: Context, serverURL: String, channel: Long) {
val workRequest = OneTimeWorkRequestBuilder<PublicChatInfoUpdateWorker>()
.setConstraints(Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
)
.setInputData(workDataOf(
DATA_KEY_SERVER_URL to serverURL,
DATA_KEY_CHANNEL to channel
))
.build()
WorkManager
.getInstance(context)
.enqueue(workRequest)
}
}
override fun doWork(): Result {
val serverUrl = inputData.getString(DATA_KEY_SERVER_URL)!!
val room = inputData.getString(DATA_KEY_ROOM)
val openGroupId = "$serverUrl.$room"
return try {
Log.v(TAG, "Updating open group info for $openGroupId.")
OpenGroupUtilities.updateGroupInfo(context, serverUrl, room!!)
Log.v(TAG, "Open group info was successfully updated for $openGroupId.")
Result.success()
} catch (e: Exception) {
Log.e(TAG, "Failed to update open group info for $openGroupId", e)
Result.failure()
}
}
}

View File

@ -1,24 +0,0 @@
package org.thoughtcrime.securesms.loki.dialogs
import android.os.Bundle
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_device_list_bottom_sheet.*
import network.loki.messenger.R
public class DeviceEditingOptionsBottomSheet : BottomSheetDialogFragment() {
var onEditTapped: (() -> Unit)? = null
var onUnlinkTapped: (() -> Unit)? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_device_list_bottom_sheet, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
editDisplayNameText.setOnClickListener { onEditTapped?.invoke() }
unlinkDeviceText.setOnClickListener { onUnlinkTapped?.invoke() }
}
}

View File

@ -1,73 +0,0 @@
package org.thoughtcrime.securesms.loki.protocol
import android.content.ContentValues
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase
import org.thoughtcrime.securesms.loki.utilities.get
import org.thoughtcrime.securesms.loki.utilities.getAll
import org.thoughtcrime.securesms.loki.utilities.getString
import org.thoughtcrime.securesms.loki.utilities.insertOrUpdate
import org.session.libsignal.utilities.Hex
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
import org.session.libsignal.crypto.ecc.DjbECPublicKey
import org.session.libsignal.crypto.ecc.ECKeyPair
import org.session.libsignal.utilities.PublicKeyValidation
import org.session.libsignal.utilities.removing05PrefixIfNeeded
import org.session.libsignal.utilities.toHexString
import java.util.*
object ClosedGroupsMigration {
public val closedGroupPublicKey = "closed_group_public_key"
// Ratchets
private val oldClosedGroupRatchetTable = "old_closed_group_ratchet_table"
private val currentClosedGroupRatchetTable = "closed_group_ratchet_table"
private val senderPublicKey = "sender_public_key"
private val chainKey = "chain_key"
private val keyIndex = "key_index"
private val messageKeys = "message_keys"
@JvmStatic val createOldClosedGroupRatchetTableCommand
= "CREATE TABLE $oldClosedGroupRatchetTable ($closedGroupPublicKey STRING, $senderPublicKey STRING, $chainKey STRING, " +
"$keyIndex INTEGER DEFAULT 0, $messageKeys TEXT, PRIMARY KEY ($closedGroupPublicKey, $senderPublicKey));"
// Private keys
@JvmStatic val createCurrentClosedGroupRatchetTableCommand
= "CREATE TABLE $currentClosedGroupRatchetTable ($closedGroupPublicKey STRING, $senderPublicKey STRING, $chainKey STRING, " +
"$keyIndex INTEGER DEFAULT 0, $messageKeys TEXT, PRIMARY KEY ($closedGroupPublicKey, $senderPublicKey));"
// Private keys
public val closedGroupPrivateKeyTable = "closed_group_private_key_table"
public val closedGroupPrivateKey = "closed_group_private_key"
@JvmStatic val createClosedGroupPrivateKeyTableCommand
= "CREATE TABLE $closedGroupPrivateKeyTable ($closedGroupPublicKey STRING PRIMARY KEY, $closedGroupPrivateKey STRING);"
fun perform(database: net.sqlcipher.database.SQLiteDatabase) {
val publicKeys = database.getAll(closedGroupPrivateKeyTable, null, null) { cursor ->
cursor.getString(closedGroupPublicKey)
}.filter {
PublicKeyValidation.isValid(it)
}
val keyPairs = mutableListOf<ECKeyPair>()
for (publicKey in publicKeys) {
val query = "${closedGroupPublicKey} = ?"
val privateKey = database.get(closedGroupPrivateKeyTable, query, arrayOf( publicKey )) { cursor ->
cursor.getString(closedGroupPrivateKey)
}
val keyPair = ECKeyPair(DjbECPublicKey(Hex.fromStringCondensed(publicKey.removing05PrefixIfNeeded())), DjbECPrivateKey(Hex.fromStringCondensed(privateKey)))
keyPairs.add(keyPair)
val row = ContentValues(1)
row.put(LokiAPIDatabase.groupPublicKey, publicKey)
database.insertOrUpdate(LokiAPIDatabase.closedGroupPublicKeysTable, row, "${LokiAPIDatabase.groupPublicKey} = ?", arrayOf( publicKey ))
}
for (keyPair in keyPairs) {
// In this particular case keyPair.publicKey == groupPublicKey
val timestamp = Date().time.toString()
val index = "${keyPair.publicKey.serialize().toHexString()}-$timestamp"
val encryptionKeyPairPublicKey = keyPair.publicKey.serialize().toHexString().removing05PrefixIfNeeded()
val encryptionKeyPairPrivateKey = keyPair.privateKey.serialize().toHexString()
val row = ContentValues(3)
row.put(LokiAPIDatabase.closedGroupsEncryptionKeyPairIndex, index)
row.put(LokiAPIDatabase.encryptionKeyPairPublicKey, encryptionKeyPairPublicKey)
row.put(LokiAPIDatabase.encryptionKeyPairPrivateKey, encryptionKeyPairPrivateKey)
database.insertOrUpdate(LokiAPIDatabase.closedGroupEncryptionKeyPairsTable, row, "${LokiAPIDatabase.closedGroupsEncryptionKeyPairIndex} = ?", arrayOf( index ))
}
}
}

View File

@ -1,392 +0,0 @@
package org.thoughtcrime.securesms.loki.protocol
import android.content.Context
import android.util.Log
import com.google.protobuf.ByteString
import org.session.libsession.messaging.sending_receiving.*
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
import org.session.libsignal.crypto.ecc.DjbECPublicKey
import org.session.libsignal.crypto.ecc.ECKeyPair
import org.session.libsignal.messages.SignalServiceGroup
import org.session.libsignal.protos.SignalServiceProtos
import org.session.libsignal.protos.SignalServiceProtos.DataMessage
import org.session.libsignal.utilities.removing05PrefixIfNeeded
import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.GroupDatabase
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager.ClosedGroupOperation
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.GroupRecord
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.TextSecurePreferences
import java.util.*
object ClosedGroupsProtocolV2 {
@JvmStatic
fun handleMessage(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) {
if (!isValid(context, closedGroupUpdate, senderPublicKey, sentTimestamp)) { return }
when (closedGroupUpdate.type) {
DataMessage.ClosedGroupControlMessage.Type.NEW -> handleNewClosedGroup(context, closedGroupUpdate, senderPublicKey, sentTimestamp)
DataMessage.ClosedGroupControlMessage.Type.MEMBERS_REMOVED -> handleClosedGroupMembersRemoved(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey)
DataMessage.ClosedGroupControlMessage.Type.MEMBERS_ADDED -> handleClosedGroupMembersAdded(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey)
DataMessage.ClosedGroupControlMessage.Type.NAME_CHANGE -> handleClosedGroupNameChange(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey)
DataMessage.ClosedGroupControlMessage.Type.MEMBER_LEFT -> handleClosedGroupMemberLeft(context, sentTimestamp, groupPublicKey, senderPublicKey)
DataMessage.ClosedGroupControlMessage.Type.ENCRYPTION_KEY_PAIR -> handleGroupEncryptionKeyPair(context, closedGroupUpdate, groupPublicKey, senderPublicKey)
else -> {
Log.d("Loki","Can't handle closed group update of unknown type: ${closedGroupUpdate.type}")
}
}
}
private fun isValid(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, senderPublicKey: String, sentTimestamp: Long): Boolean {
val record = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(sentTimestamp, senderPublicKey)
if (record != null) return false
return when (closedGroupUpdate.type) {
DataMessage.ClosedGroupControlMessage.Type.NEW -> {
(!closedGroupUpdate.publicKey.isEmpty && !closedGroupUpdate.name.isNullOrEmpty() && !(closedGroupUpdate.encryptionKeyPair.privateKey ?: ByteString.copyFrom(ByteArray(0))).isEmpty
&& !(closedGroupUpdate.encryptionKeyPair.publicKey ?: ByteString.copyFrom(ByteArray(0))).isEmpty && closedGroupUpdate.membersCount > 0 && closedGroupUpdate.adminsCount > 0)
}
DataMessage.ClosedGroupControlMessage.Type.MEMBERS_ADDED,
DataMessage.ClosedGroupControlMessage.Type.MEMBERS_REMOVED -> {
closedGroupUpdate.membersCount > 0
}
DataMessage.ClosedGroupControlMessage.Type.MEMBER_LEFT -> {
senderPublicKey.isNotEmpty()
}
DataMessage.ClosedGroupControlMessage.Type.NAME_CHANGE -> {
!closedGroupUpdate.name.isNullOrEmpty()
}
DataMessage.ClosedGroupControlMessage.Type.ENCRYPTION_KEY_PAIR -> true
else -> false
}
}
public fun handleNewClosedGroup(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, senderPublicKey: String, sentTimestamp: Long) {
// Prepare
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
// Unwrap the message
val groupPublicKey = closedGroupUpdate.publicKey.toByteArray().toHexString()
val name = closedGroupUpdate.name
val encryptionKeyPairAsProto = closedGroupUpdate.encryptionKeyPair
val members = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() }
val admins = closedGroupUpdate.adminsList.map { it.toByteArray().toHexString() }
// Create the group
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val groupDB = DatabaseFactory.getGroupDatabase(context)
val prevGroup = groupDB.getGroup(groupID).orNull()
if (prevGroup != null) {
// Update the group
groupDB.updateTitle(groupID, name)
groupDB.updateMembers(groupID, members.map { Address.fromSerialized(it) })
} else {
groupDB.create(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }),
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), sentTimestamp)
}
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(Recipient.from(context, Address.fromSerialized(groupID), false), true)
// Add the group to the user's set of public keys to poll for
apiDB.addClosedGroupPublicKey(groupPublicKey)
// Store the encryption key pair
val encryptionKeyPair = ECKeyPair(DjbECPublicKey(encryptionKeyPairAsProto.publicKey.toByteArray().removing05PrefixIfNeeded()), DjbECPrivateKey(encryptionKeyPairAsProto.privateKey.toByteArray()))
apiDB.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
// Notify the user (if we didn't make the group)
if (userPublicKey != senderPublicKey) {
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp)
} else if (prevGroup == null) {
// only notify if we created this group
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
}
// Notify the PN server
LokiPushNotificationManager.performOperation(context, ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey)
}
fun handleClosedGroupMembersRemoved(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) {
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
return
}
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val name = group.title
// Check common group update logic
val members = group.members.map { it.serialize() }
val admins = group.admins.map { it.toString() }
// Users that are part of this remove update
val updateMembers = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() }
if (!isValidGroupUpdate(group, sentTimestamp, senderPublicKey)) {
return
}
// If admin leaves the group is disbanded
val didAdminLeave = admins.any { it in updateMembers }
// newMembers to save is old members minus removed members
val newMembers = members - updateMembers
// user should be posting MEMBERS_LEFT so this should not be encountered
val senderLeft = senderPublicKey in updateMembers
if (senderLeft) {
Log.d("Loki", "Received a MEMBERS_REMOVED instead of a MEMBERS_LEFT from sender $senderPublicKey")
}
val wasCurrentUserRemoved = userPublicKey in updateMembers
// admin should send a MEMBERS_LEFT message but handled here in case
if (didAdminLeave || wasCurrentUserRemoved) {
disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey)
} else {
val isCurrentUserAdmin = admins.contains(userPublicKey)
groupDB.updateMembers(groupID, newMembers.map { Address.fromSerialized(it) })
if (isCurrentUserAdmin) {
MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, newMembers)
}
}
val type =
if (senderLeft) SignalServiceGroup.Type.QUIT
else SignalServiceGroup.Type.UPDATE
if (userPublicKey == senderPublicKey) {
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, type, name, members, admins, threadID, sentTimestamp)
} else {
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, type, name, members, admins, sentTimestamp)
}
}
fun handleClosedGroupMembersAdded(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) {
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
return
}
// Check common group update logic
if (!isValidGroupUpdate(group, sentTimestamp, senderPublicKey)) {
return
}
val name = group.title
val members = group.members.map { it.serialize() }
val admins = group.admins.map { it.serialize() }
// Users that are part of this add update
val updateMembers = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() }
// newMembers to save is old members plus members included in this update
val newMembers = members + updateMembers
groupDB.updateMembers(groupID, newMembers.map { Address.fromSerialized(it) })
if (userPublicKey == senderPublicKey) {
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
} else {
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp)
}
if (userPublicKey in admins) {
// send current encryption key to the latest added members
val encryptionKeyPair = pendingKeyPairs[groupPublicKey]?.orNull()
?: apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey)
if (encryptionKeyPair == null) {
Log.d("Loki", "Couldn't get encryption key pair for closed group.")
} else {
for (user in updateMembers) {
MessageSender.sendEncryptionKeyPair(groupPublicKey, encryptionKeyPair, setOf(user), targetUser = user, force = false)
}
}
}
}
fun handleClosedGroupNameChange(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) {
// Check that the sender is a member of the group (before the update)
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
return
}
// Check common group update logic
if (!isValidGroupUpdate(group, sentTimestamp, senderPublicKey)) {
return
}
val members = group.members.map { it.serialize() }
val admins = group.admins.map { it.serialize() }
val name = closedGroupUpdate.name
groupDB.updateTitle(groupID, name)
// Notify the user
if (userPublicKey == senderPublicKey) {
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, threadID, sentTimestamp)
} else {
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp)
}
}
private fun handleClosedGroupMemberLeft(context: Context, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) {
// Check the user leaving isn't us, will already be handled
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
return
}
val name = group.title
// Check common group update logic
val members = group.members.map { it.serialize() }
val admins = group.admins.map { it.toString() }
if (!isValidGroupUpdate(group, sentTimestamp, senderPublicKey)) {
return
}
// If the admin leaves the group is disbanded
val didAdminLeave = admins.contains(senderPublicKey)
val updatedMemberList = members - senderPublicKey
val userLeft = (userPublicKey == senderPublicKey)
// if the admin left, we left, or we are the only remaining member: remove the group
if (didAdminLeave || userLeft) {
disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey)
} else {
val isCurrentUserAdmin = admins.contains(userPublicKey)
groupDB.updateMembers(groupID, updatedMemberList.map { Address.fromSerialized(it) })
if (isCurrentUserAdmin) {
MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, updatedMemberList)
}
}
// Notify user
if (userLeft) {
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.QUIT, name, members, admins, threadID, sentTimestamp)
} else {
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceGroup.Type.QUIT, name, members, admins, sentTimestamp)
}
}
private fun disableLocalGroupAndUnsubscribe(context: Context, apiDB: LokiAPIDatabase, groupPublicKey: String, groupDB: GroupDatabase, groupID: String, userPublicKey: String) {
apiDB.removeClosedGroupPublicKey(groupPublicKey)
// Remove the key pairs
apiDB.removeAllClosedGroupEncryptionKeyPairs(groupPublicKey)
// Mark the group as inactive
groupDB.setActive(groupID, false)
groupDB.removeMember(groupID, Address.fromSerialized(userPublicKey))
// Notify the PN server
LokiPushNotificationManager.performOperation(context, ClosedGroupOperation.Unsubscribe, groupPublicKey, userPublicKey)
}
private fun isValidGroupUpdate(group: GroupRecord,
sentTimestamp: Long,
senderPublicKey: String): Boolean {
val oldMembers = group.members.map { it.serialize() }
// Check that the message isn't from before the group was created
// TODO: We should check that formationTimestamp is the sent timestamp of the closed group update that created the group
if (group.formationTimestamp > sentTimestamp) {
Log.d("Loki", "Ignoring closed group update from before thread was created.")
return false
}
// Check that the sender is a member of the group (before the update)
if (senderPublicKey !in oldMembers) {
Log.d("Loki", "Ignoring closed group info message from non-member.")
return false
}
return true
}
private fun handleGroupEncryptionKeyPair(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, groupPublicKey: String, senderPublicKey: String) {
// Prepare
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val userKeyPair = apiDB.getUserX25519KeyPair()
// Unwrap the message
val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupPublicKeyToUse = when {
groupPublicKey.isNotEmpty() -> groupPublicKey
!closedGroupUpdate.publicKey.isEmpty -> closedGroupUpdate.publicKey.toByteArray().toHexString()
else -> ""
}
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKeyToUse)
val group = groupDB.getGroup(groupID).orNull()
if (group == null) {
Log.d("Loki", "Ignoring closed group encryption key pair message for nonexistent group.")
return
}
if (!group.admins.map { it.toString() }.contains(senderPublicKey)) {
Log.d("Loki", "Ignoring closed group encryption key pair from non-admin.")
return
}
// Find our wrapper and decrypt it if possible
val wrapper = closedGroupUpdate.wrappersList.firstOrNull { it.publicKey.toByteArray().toHexString() == userPublicKey } ?: return
val encryptedKeyPair = wrapper.encryptedKeyPair.toByteArray()
val plaintext = MessageDecrypter.decrypt(encryptedKeyPair, userKeyPair).first
// Parse it
val proto = SignalServiceProtos.KeyPair.parseFrom(plaintext)
val keyPair = ECKeyPair(DjbECPublicKey(proto.publicKey.toByteArray().removing05PrefixIfNeeded()), DjbECPrivateKey(proto.privateKey.toByteArray()))
// Store it
apiDB.addClosedGroupEncryptionKeyPair(keyPair, groupPublicKeyToUse)
Log.d("Loki", "Received a new closed group encryption key pair")
}
// region Deprecated
private fun handleClosedGroupUpdate(context: Context, closedGroupUpdate: DataMessage.ClosedGroupControlMessage, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) {
// Prepare
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
// Unwrap the message
val name = closedGroupUpdate.name
val members = closedGroupUpdate.membersList.map { it.toByteArray().toHexString() }
val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull()
if (group == null || !group.isActive) {
Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.")
return
}
val oldMembers = group.members.map { it.serialize() }
// Check common group update logic
if (!isValidGroupUpdate(group, sentTimestamp, senderPublicKey)) {
return
}
// Check that the admin wasn't removed unless the group was destroyed entirely
if (!members.contains(group.admins.first().toString()) && members.isNotEmpty()) {
Log.d("Loki", "Ignoring invalid closed group update message.")
return
}
// Remove the group from the user's set of public keys to poll for if the current user was removed
val wasCurrentUserRemoved = !members.contains(userPublicKey)
if (wasCurrentUserRemoved) {
disableLocalGroupAndUnsubscribe(context, apiDB, groupPublicKey, groupDB, groupID, userPublicKey)
}
// Generate and distribute a new encryption key pair if needed
val wasAnyUserRemoved = (members.toSet().intersect(oldMembers) != oldMembers.toSet())
val isCurrentUserAdmin = group.admins.map { it.toString() }.contains(userPublicKey)
if (wasAnyUserRemoved && isCurrentUserAdmin) {
MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, members)
}
// Update the group
groupDB.updateTitle(groupID, name)
if (!wasCurrentUserRemoved) {
// The call below sets isActive to true, so if the user is leaving we have to use groupDB.remove(...) instead
groupDB.updateMembers(groupID, members.map { Address.fromSerialized(it) })
}
// Notify the user
val wasSenderRemoved = !members.contains(senderPublicKey)
val type = if (wasSenderRemoved) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.UPDATE
val admins = group.admins.map { it.toString() }
if (userPublicKey == senderPublicKey) {
val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID)
DatabaseFactory.getStorage(context).insertOutgoingInfoMessage(context, groupID, type, name, members, admins, threadID, sentTimestamp)
} else {
DatabaseFactory.getStorage(context).insertIncomingInfoMessage(context, senderPublicKey, groupID, type, name, members, admins, sentTimestamp)
}
}
// endregion
}

View File

@ -1,335 +0,0 @@
package org.thoughtcrime.securesms.loki.views
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.drawable.AnimatedVectorDrawable
import android.util.AttributeSet
import android.view.View
import android.view.View.OnTouchListener
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import kotlinx.coroutines.*
import network.loki.messenger.R
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
import org.thoughtcrime.securesms.ApplicationContext
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.audio.AudioSlidePlayer
import org.thoughtcrime.securesms.components.AnimatingToggle
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.events.PartProgressEvent
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.loki.api.PrepareAttachmentAudioExtrasJob
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.mms.AudioSlide
import org.thoughtcrime.securesms.mms.SlideClickListener
import java.io.IOException
import java.util.*
import java.util.concurrent.TimeUnit
class MessageAudioView: FrameLayout, AudioSlidePlayer.Listener {
companion object {
private const val TAG = "AudioViewKt"
}
private val controlToggle: AnimatingToggle
private val container: ViewGroup
private val playButton: ImageView
private val pauseButton: ImageView
private val downloadButton: ImageView
private val downloadProgress: ProgressBar
private val seekBar: WaveformSeekBar
private val totalDuration: TextView
private var downloadListener: SlideClickListener? = null
private var audioSlidePlayer: AudioSlidePlayer? = null
/** Background coroutine scope that is available when the view is attached to a window. */
private var asyncCoroutineScope: CoroutineScope? = null
private val loadingAnimation: SeekBarLoadingAnimation
constructor(context: Context): this(context, null)
constructor(context: Context, attrs: AttributeSet?): this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr) {
View.inflate(context, R.layout.message_audio_view, this)
container = findViewById(R.id.audio_widget_container)
controlToggle = findViewById(R.id.control_toggle)
playButton = findViewById(R.id.play)
pauseButton = findViewById(R.id.pause)
downloadButton = findViewById(R.id.download)
downloadProgress = findViewById(R.id.download_progress)
seekBar = findViewById(R.id.seek)
totalDuration = findViewById(R.id.total_duration)
playButton.setOnClickListener {
try {
Log.d(TAG, "playbutton onClick")
if (audioSlidePlayer != null) {
togglePlayToPause()
// Restart the playback if progress bar is nearly at the end.
val progress = if (seekBar.progress < 0.99f) seekBar.progress.toDouble() else 0.0
audioSlidePlayer!!.play(progress)
}
} catch (e: IOException) {
Log.w(TAG, e)
}
}
pauseButton.setOnClickListener {
Log.d(TAG, "pausebutton onClick")
if (audioSlidePlayer != null) {
togglePauseToPlay()
audioSlidePlayer!!.stop()
}
}
seekBar.isEnabled = false
seekBar.progressChangeListener = object : WaveformSeekBar.ProgressChangeListener {
override fun onProgressChanged(waveformSeekBar: WaveformSeekBar, progress: Float, fromUser: Boolean) {
if (fromUser && audioSlidePlayer != null) {
synchronized(audioSlidePlayer!!) {
audioSlidePlayer!!.seekTo(progress.toDouble())
}
}
}
}
playButton.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.play_icon))
pauseButton.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.pause_icon))
playButton.background = ContextCompat.getDrawable(context, R.drawable.ic_circle_fill_white_48dp)
pauseButton.background = ContextCompat.getDrawable(context, R.drawable.ic_circle_fill_white_48dp)
if (attrs != null) {
val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.MessageAudioView, 0, 0)
setTint(typedArray.getColor(R.styleable.MessageAudioView_foregroundTintColor, Color.WHITE),
typedArray.getColor(R.styleable.MessageAudioView_waveformFillColor, Color.WHITE),
typedArray.getColor(R.styleable.MessageAudioView_waveformBackgroundColor, Color.WHITE))
container.setBackgroundColor(typedArray.getColor(R.styleable.MessageAudioView_widgetBackground, Color.TRANSPARENT))
typedArray.recycle()
}
loadingAnimation = SeekBarLoadingAnimation(this, seekBar)
loadingAnimation.start()
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
if (!EventBus.getDefault().isRegistered(this)) EventBus.getDefault().register(this)
asyncCoroutineScope = CoroutineScope(Job() + Dispatchers.IO)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
EventBus.getDefault().unregister(this)
// Cancel all the background operations.
asyncCoroutineScope!!.cancel()
asyncCoroutineScope = null
}
fun setAudio(audio: AudioSlide, showControls: Boolean) {
when {
showControls && audio.isPendingDownload -> {
controlToggle.displayQuick(downloadButton)
seekBar.isEnabled = false
downloadButton.setOnClickListener { v -> downloadListener?.onClick(v, audio) }
if (downloadProgress.isIndeterminate) {
downloadProgress.isIndeterminate = false
downloadProgress.progress = 0
}
}
(showControls && audio.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_STARTED) -> {
controlToggle.displayQuick(downloadProgress)
seekBar.isEnabled = false
downloadProgress.isIndeterminate = true
}
else -> {
controlToggle.displayQuick(playButton)
seekBar.isEnabled = true
if (downloadProgress.isIndeterminate) {
downloadProgress.isIndeterminate = false
downloadProgress.progress = 100
}
// Post to make sure it executes only when the view is attached to a window.
post(::updateFromAttachmentAudioExtras)
}
}
audioSlidePlayer = AudioSlidePlayer.createFor(context, audio, this)
}
fun cleanup() {
if (audioSlidePlayer != null && pauseButton.visibility == View.VISIBLE) {
audioSlidePlayer!!.stop()
}
}
fun setDownloadClickListener(listener: SlideClickListener?) {
downloadListener = listener
}
fun setTint(@ColorInt foregroundTint: Int, @ColorInt waveformFill: Int, @ColorInt waveformBackground: Int) {
playButton.backgroundTintList = ColorStateList.valueOf(resources.getColorWithID(R.color.white, context.theme))
playButton.imageTintList = ColorStateList.valueOf(resources.getColorWithID(R.color.black, context.theme))
pauseButton.backgroundTintList = ColorStateList.valueOf(resources.getColorWithID(R.color.white, context.theme))
pauseButton.imageTintList = ColorStateList.valueOf(resources.getColorWithID(R.color.black, context.theme))
downloadButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN)
downloadProgress.backgroundTintList = ColorStateList.valueOf(resources.getColorWithID(R.color.white, context.theme))
downloadProgress.progressTintList = ColorStateList.valueOf(resources.getColorWithID(R.color.black, context.theme))
downloadProgress.indeterminateTintList = ColorStateList.valueOf(resources.getColorWithID(R.color.black, context.theme))
totalDuration.setTextColor(foregroundTint)
seekBar.barProgressColor = waveformFill
seekBar.barBackgroundColor = waveformBackground
}
override fun onPlayerStart(player: AudioSlidePlayer) {
if (pauseButton.visibility != View.VISIBLE) {
togglePlayToPause()
}
}
override fun onPlayerStop(player: AudioSlidePlayer) {
if (playButton.visibility != View.VISIBLE) {
togglePauseToPlay()
}
}
override fun onPlayerProgress(player: AudioSlidePlayer, progress: Double, millis: Long) {
seekBar.progress = progress.toFloat()
}
override fun setFocusable(focusable: Boolean) {
super.setFocusable(focusable)
playButton.isFocusable = focusable
pauseButton.isFocusable = focusable
seekBar.isFocusable = focusable
seekBar.isFocusableInTouchMode = focusable
downloadButton.isFocusable = focusable
}
override fun setClickable(clickable: Boolean) {
super.setClickable(clickable)
playButton.isClickable = clickable
pauseButton.isClickable = clickable
seekBar.isClickable = clickable
seekBar.setOnTouchListener(if (clickable) null else
OnTouchListener { _, _ -> return@OnTouchListener true }) // Suppress touch events.
downloadButton.isClickable = clickable
}
override fun setEnabled(enabled: Boolean) {
super.setEnabled(enabled)
playButton.isEnabled = enabled
pauseButton.isEnabled = enabled
downloadButton.isEnabled = enabled
}
private fun togglePlayToPause() {
controlToggle.displayQuick(pauseButton)
val playToPauseDrawable = ContextCompat.getDrawable(context, R.drawable.play_to_pause_animation) as AnimatedVectorDrawable
pauseButton.setImageDrawable(playToPauseDrawable)
playToPauseDrawable.start()
}
private fun togglePauseToPlay() {
controlToggle.displayQuick(playButton)
val pauseToPlayDrawable = ContextCompat.getDrawable(context, R.drawable.pause_to_play_animation) as AnimatedVectorDrawable
playButton.setImageDrawable(pauseToPlayDrawable)
pauseToPlayDrawable.start()
}
private fun obtainDatabaseAttachment(): DatabaseAttachment? {
audioSlidePlayer ?: return null
val attachment = audioSlidePlayer!!.audioSlide.asAttachment()
return if (attachment is DatabaseAttachment) attachment else null
}
private fun updateFromAttachmentAudioExtras() {
val attachment = obtainDatabaseAttachment() ?: return
val audioExtras = DatabaseFactory.getAttachmentDatabase(context)
.getAttachmentAudioExtras(attachment.attachmentId)
// Schedule a job request if no audio extras were generated yet.
if (audioExtras == null) {
ApplicationContext.getInstance(context).jobManager
.add(PrepareAttachmentAudioExtrasJob(attachment.attachmentId))
return
}
loadingAnimation.stop()
seekBar.sampleData = audioExtras.visualSamples
if (audioExtras.durationMs > 0) {
totalDuration.visibility = View.VISIBLE
totalDuration.text = String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(audioExtras.durationMs),
TimeUnit.MILLISECONDS.toSeconds(audioExtras.durationMs))
}
}
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
fun onEvent(event: PartProgressEvent) {
if (audioSlidePlayer != null && event.attachment == audioSlidePlayer!!.audioSlide.asAttachment()) {
val progress = ((event.progress.toFloat() / event.total) * 100f).toInt()
downloadProgress.progress = progress
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEvent(event: PrepareAttachmentAudioExtrasJob.AudioExtrasUpdatedEvent) {
if (event.attachmentId == obtainDatabaseAttachment()?.attachmentId) {
updateFromAttachmentAudioExtras()
}
}
private class SeekBarLoadingAnimation(
private val hostView: View,
private val seekBar: WaveformSeekBar): Runnable {
private var active = false
companion object {
private const val UPDATE_PERIOD = 250L // In milliseconds.
private val random = Random()
}
fun start() {
stop()
active = true
hostView.postDelayed(this, UPDATE_PERIOD)
}
fun stop() {
active = false
hostView.removeCallbacks(this)
}
override fun run() {
if (!active) return
// Generate a random samples with values up to the 50% of the maximum value.
seekBar.sampleData = ByteArray(PrepareAttachmentAudioExtrasJob.VISUAL_RMS_FRAMES)
{ (random.nextInt(127) - 64).toByte() }
hostView.postDelayed(this, UPDATE_PERIOD)
}
}
}

View File

@ -1,71 +0,0 @@
package org.thoughtcrime.securesms.loki.views
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.*
import androidx.appcompat.app.AlertDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import network.loki.messenger.R
import org.session.libsession.utilities.OpenGroupUrlParser
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.loki.api.OpenGroupManager
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
class OpenGroupInvitationView : FrameLayout {
private val joinButton: ImageView
private val openGroupIconContainer: RelativeLayout
private val openGroupIconImageView: ImageView
private val nameTextView: TextView
private val urlTextView: TextView
private var url: String = ""
constructor(context: Context): this(context, null)
constructor(context: Context, attrs: AttributeSet?): this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr) {
View.inflate(context, R.layout.open_group_invitation_view, this)
joinButton = findViewById(R.id.join_open_group_button)
openGroupIconContainer = findViewById(R.id.open_group_icon_image_view_container)
openGroupIconImageView = findViewById(R.id.open_group_icon_image_view)
nameTextView = findViewById(R.id.name_text_view)
urlTextView = findViewById(R.id.url_text_view)
joinButton.setOnClickListener { joinOpenGroup(url) }
}
fun setOpenGroup(name: String, url: String, isOutgoing: Boolean = false) {
nameTextView.text = name
urlTextView.text = OpenGroupUrlParser.trimQueryParameter(url)
this.url = url
joinButton.visibility = if (isOutgoing) View.GONE else View.VISIBLE
openGroupIconContainer.visibility = if (isOutgoing) View.VISIBLE else View.GONE
}
private fun joinOpenGroup(url: String) {
val openGroup = OpenGroupUrlParser.parseUrl(url)
val builder = AlertDialog.Builder(context)
builder.setTitle(context.getString(R.string.ConversationActivity_join_open_group, nameTextView.text.toString()))
builder.setCancelable(true)
val message: String =
context.getString(R.string.ConversationActivity_join_open_group_confirmation_message, nameTextView.text.toString())
builder.setMessage(message)
builder.setPositiveButton(R.string.yes) { dialog, _ ->
GlobalScope.launch(Dispatchers.IO) {
try {
dialog.dismiss()
OpenGroupManager.add(openGroup.server, openGroup.room, openGroup.serverPublicKey, context)
MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(context)
} catch (e: Exception) {
Log.e("Loki", "Failed to join open group.", e)
Toast.makeText(context, R.string.activity_join_public_chat_error, Toast.LENGTH_SHORT).show()
}
}
}
builder.setNegativeButton(R.string.no, null)
builder.show()
}
}

View File

@ -1,315 +0,0 @@
package org.thoughtcrime.securesms.loki.views
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.util.TypedValue
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.view.animation.DecelerateInterpolator
import androidx.core.math.MathUtils
import network.loki.messenger.R
import org.session.libsession.utilities.byteToNormalizedFloat
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
class WaveformSeekBar : View {
companion object {
@JvmStatic
fun dp(context: Context, dp: Float): Float {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
context.resources.displayMetrics
)
}
}
private val sampleDataHolder = SampleDataHolder(::invalidate)
/** An array of signed byte values representing the audio signal. */
var sampleData: ByteArray?
get() {
return sampleDataHolder.getSamples()
}
set(value) {
sampleDataHolder.setSamples(value)
invalidate()
}
/** Indicates whether the user is currently interacting with the view and performing a seeking gesture. */
private var userSeeking = false
private var _progress: Float = 0f
/** In [0..1] range. */
var progress: Float
set(value) {
// Do not let to modify the progress value from the outside
// when the user is currently interacting with the view.
if (userSeeking) return
_progress = value
invalidate()
progressChangeListener?.onProgressChanged(this, _progress, false)
}
get() {
return _progress
}
var barBackgroundColor: Int = Color.LTGRAY
set(value) {
field = value
invalidate()
}
var barProgressColor: Int = Color.WHITE
set(value) {
field = value
invalidate()
}
var barGap: Float = dp(context, 2f)
set(value) {
field = value
invalidate()
}
var barWidth: Float = dp(context, 5f)
set(value) {
field = value
invalidate()
}
var barMinHeight: Float = barWidth
set(value) {
field = value
invalidate()
}
var barCornerRadius: Float = dp(context, 2.5f)
set(value) {
field = value
invalidate()
}
var barGravity: WaveGravity = WaveGravity.CENTER
set(value) {
field = value
invalidate()
}
var progressChangeListener: ProgressChangeListener? = null
private val barPaint = Paint(Paint.ANTI_ALIAS_FLAG)
private val barRect = RectF()
private var canvasWidth = 0
private var canvasHeight = 0
private var touchDownX = 0f
private var touchDownProgress: Float = 0f
private var scaledTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int)
: super(context, attrs, defStyleAttr) {
val typedAttrs = context.obtainStyledAttributes(attrs, R.styleable.WaveformSeekBar)
barWidth = typedAttrs.getDimension(R.styleable.WaveformSeekBar_bar_width, barWidth)
barGap = typedAttrs.getDimension(R.styleable.WaveformSeekBar_bar_gap, barGap)
barCornerRadius = typedAttrs.getDimension(
R.styleable.WaveformSeekBar_bar_corner_radius,
barCornerRadius)
barMinHeight =
typedAttrs.getDimension(R.styleable.WaveformSeekBar_bar_min_height, barMinHeight)
barBackgroundColor = typedAttrs.getColor(
R.styleable.WaveformSeekBar_bar_background_color,
barBackgroundColor)
barProgressColor =
typedAttrs.getColor(R.styleable.WaveformSeekBar_bar_progress_color, barProgressColor)
progress = typedAttrs.getFloat(R.styleable.WaveformSeekBar_progress, progress)
barGravity = WaveGravity.fromString(
typedAttrs.getString(R.styleable.WaveformSeekBar_bar_gravity))
typedAttrs.recycle()
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
canvasWidth = w
canvasHeight = h
invalidate()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val totalWidth = getAvailableWidth()
val barAmount = (totalWidth / (barWidth + barGap)).toInt()
var lastBarRight = paddingLeft.toFloat()
(0 until barAmount).forEach { barIdx ->
// Convert a signed byte to a [0..1] float.
val barValue = byteToNormalizedFloat(sampleDataHolder.computeBarValue(barIdx, barAmount))
val barHeight = max(barMinHeight, getAvailableHeight() * barValue)
val top: Float = when (barGravity) {
WaveGravity.TOP -> paddingTop.toFloat()
WaveGravity.CENTER -> paddingTop + getAvailableHeight() * 0.5f - barHeight * 0.5f
WaveGravity.BOTTOM -> canvasHeight - paddingBottom - barHeight
}
barRect.set(lastBarRight, top, lastBarRight + barWidth, top + barHeight)
barPaint.color = if (barRect.right <= totalWidth * progress)
barProgressColor else barBackgroundColor
canvas.drawRoundRect(barRect, barCornerRadius, barCornerRadius, barPaint)
lastBarRight = barRect.right + barGap
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
if (!isEnabled) return false
when (event.action) {
MotionEvent.ACTION_DOWN -> {
userSeeking = true
touchDownX = event.x
touchDownProgress = progress
updateProgress(event, false)
}
MotionEvent.ACTION_MOVE -> {
// Prevent any parent scrolling if the user scrolled more
// than scaledTouchSlop on horizontal axis.
if (abs(event.x - touchDownX) > scaledTouchSlop) {
parent.requestDisallowInterceptTouchEvent(true)
}
updateProgress(event, false)
}
MotionEvent.ACTION_UP -> {
userSeeking = false
updateProgress(event, true)
performClick()
}
MotionEvent.ACTION_CANCEL -> {
updateProgress(touchDownProgress, false)
userSeeking = false
}
}
return true
}
private fun updateProgress(event: MotionEvent, notify: Boolean) {
updateProgress(event.x / getAvailableWidth(), notify)
}
private fun updateProgress(progress: Float, notify: Boolean) {
_progress = MathUtils.clamp(progress, 0f, 1f)
invalidate()
if (notify) {
progressChangeListener?.onProgressChanged(this, _progress, true)
}
}
override fun performClick(): Boolean {
super.performClick()
return true
}
private fun getAvailableWidth() = canvasWidth - paddingLeft - paddingRight
private fun getAvailableHeight() = canvasHeight - paddingTop - paddingBottom
private class SampleDataHolder(private val invalidateDelegate: () -> Any) {
private var sampleDataFrom: ByteArray? = null
private var sampleDataTo: ByteArray? = null
private var progress = 1f // Mix between from and to values.
private var animation: ValueAnimator? = null
fun computeBarValue(barIdx: Int, barAmount: Int): Byte {
/** @return The array's value at the interpolated index. */
fun getSampleValue(sampleData: ByteArray?): Byte {
if (sampleData == null || sampleData.isEmpty())
return Byte.MIN_VALUE
else {
val sampleIdx = (barIdx * (sampleData.size / barAmount.toFloat())).toInt()
return sampleData[sampleIdx]
}
}
if (progress == 1f) {
return getSampleValue(sampleDataTo)
}
val fromValue = getSampleValue(sampleDataFrom)
val toValue = getSampleValue(sampleDataTo)
val rawResultValue = fromValue * (1f - progress) + toValue * progress
return rawResultValue.roundToInt().toByte()
}
fun setSamples(sampleData: ByteArray?) {
/** @return a mix between [sampleDataFrom] and [sampleDataTo] arrays according to the current [progress] value. */
fun computeNewDataFromArray(): ByteArray? {
if (sampleDataTo == null) return null
if (sampleDataFrom == null) return sampleDataTo
val sampleSize = min(sampleDataFrom!!.size, sampleDataTo!!.size)
return ByteArray(sampleSize) { i -> computeBarValue(i, sampleSize) }
}
sampleDataFrom = computeNewDataFromArray()
sampleDataTo = sampleData
progress = 0f
animation?.cancel()
animation = ValueAnimator.ofFloat(0f, 1f).apply {
addUpdateListener { animation ->
progress = animation.animatedValue as Float
invalidateDelegate()
}
interpolator = DecelerateInterpolator(3f)
duration = 500
start()
}
}
fun getSamples(): ByteArray? {
return sampleDataTo
}
}
enum class WaveGravity {
TOP,
CENTER,
BOTTOM,
;
companion object {
@JvmStatic
fun fromString(gravity: String?): WaveGravity = when (gravity) {
"1" -> TOP
"2" -> CENTER
else -> BOTTOM
}
}
}
interface ProgressChangeListener {
fun onProgressChanged(waveformSeekBar: WaveformSeekBar, progress: Float, fromUser: Boolean)
}
}

View File

@ -15,7 +15,7 @@ import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities;
import network.loki.messenger.R;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.api
package org.thoughtcrime.securesms.notifications
import android.content.BroadcastReceiver
import android.content.Context

View File

@ -57,9 +57,8 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.SpanUtil;

View File

@ -1,5 +1,5 @@
@file:JvmName("FcmUtils")
package org.thoughtcrime.securesms.loki.utilities
package org.thoughtcrime.securesms.notifications
import com.google.android.gms.tasks.Task
import com.google.firebase.iid.FirebaseInstanceId

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.api
package org.thoughtcrime.securesms.notifications
import android.content.Context
import nl.komponents.kovenant.functional.map

View File

@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.ExpirationInfo;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import java.util.LinkedList;

View File

@ -16,8 +16,8 @@ import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.thoughtcrime.securesms.database.SessionContactDatabase;
import java.util.LinkedList;
import java.util.List;

View File

@ -10,10 +10,9 @@ import org.session.libsession.messaging.sending_receiving.notifications.MessageN
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.Debouncer;
import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.ThreadUtils;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
import org.thoughtcrime.securesms.groups.OpenGroupManager;
import java.util.concurrent.TimeUnit;

View File

@ -7,7 +7,7 @@ import android.content.Intent;
import androidx.core.app.NotificationCompat;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
import org.thoughtcrime.securesms.home.HomeActivity;
import org.session.libsession.utilities.NotificationPrivacyPreference;
import org.session.libsession.utilities.TextSecurePreferences;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.api
package org.thoughtcrime.securesms.notifications
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
@ -10,7 +10,6 @@ import org.session.libsession.messaging.utilities.MessageWrapper
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Base64
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.notifications.NotificationChannels
class PushNotificationService : FirebaseMessagingService() {

View File

@ -28,8 +28,8 @@ import org.session.libsession.avatars.GeneratedContactPhoto;
import org.session.libsession.messaging.contacts.Contact;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
import org.thoughtcrime.securesms.loki.utilities.AvatarPlaceholderGenerator;
import org.thoughtcrime.securesms.database.SessionContactDatabase;
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.Slide;

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.onboarding
import android.content.Intent
import android.os.Bundle
@ -11,8 +11,8 @@ import kotlinx.android.synthetic.main.activity_display_name.*
import network.loki.messenger.R
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.loki.utilities.push
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.util.push
import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo
import org.session.libsession.utilities.TextSecurePreferences
class DisplayNameActivity : BaseActionBarActivity() {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.views
package org.thoughtcrime.securesms.onboarding
import android.animation.FloatEvaluator
import android.animation.ValueAnimator
@ -12,7 +12,7 @@ import android.widget.LinearLayout
import android.widget.ScrollView
import kotlinx.android.synthetic.main.view_fake_chat.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.disableClipping
import org.thoughtcrime.securesms.util.disableClipping
class FakeChatView : ScrollView {

View File

@ -1,4 +1,4 @@
package org.thoughtcrime.securesms.loki.activities
package org.thoughtcrime.securesms.onboarding
import android.content.Intent
import android.os.Bundle
@ -7,11 +7,9 @@ import network.loki.messenger.R
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.loki.utilities.push
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.loki.views.FakeChatView
import org.thoughtcrime.securesms.util.push
import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.service.KeyCachingService
import org.thoughtcrime.securesms.util.Util
class LandingActivity : BaseActionBarActivity() {

Some files were not shown because too many files have changed in this diff Show More