mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-15 18:20:14 +00:00
Performed a PR pass to fix up anything obvious - there's still a few things left TODO
This commit is contained in:
@@ -225,7 +225,7 @@ dependencies {
|
||||
|
||||
ksp("androidx.hilt:hilt-compiler:$jetpackHiltVersion")
|
||||
ksp("com.google.dagger:hilt-compiler:$daggerHiltVersion")
|
||||
ksp "com.github.bumptech.glide:ksp:$glideVersion"
|
||||
ksp("com.github.bumptech.glide:ksp:$glideVersion")
|
||||
|
||||
implementation 'androidx.compose.material3:material3-android:1.2.1'
|
||||
implementation("com.google.dagger:hilt-android:$daggerHiltVersion")
|
||||
@@ -273,7 +273,6 @@ dependencies {
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
|
||||
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
||||
implementation "com.github.bumptech.glide:compose:1.0.0-beta01"
|
||||
ksp "com.github.bumptech.glide:ksp:$glideVersion"
|
||||
implementation 'com.makeramen:roundedimageview:2.1.0'
|
||||
implementation 'com.pnikosis:materialish-progress:1.5'
|
||||
implementation 'org.greenrobot:eventbus:3.0.0'
|
||||
|
@@ -268,13 +268,6 @@
|
||||
android:theme="@style/Theme.Session.DayNight.NoActionBar"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.MediaOverviewActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.Session.DayNight.NoActionBar"
|
||||
android:windowSoftInputMode="stateHidden" />
|
||||
<activity
|
||||
android:name="org.thoughtcrime.securesms.DummyActivity"
|
||||
android:allowTaskReparenting="true"
|
||||
|
@@ -405,7 +405,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||
@SuppressWarnings("CodeBlock2Expr")
|
||||
@SuppressLint("InlinedApi")
|
||||
private void saveToDisk() {
|
||||
Log.w("ACL", "Asked to save to disk!");
|
||||
MediaItem mediaItem = getCurrentMediaItem();
|
||||
if (mediaItem == null) return;
|
||||
|
||||
@@ -487,6 +486,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||
super.onOptionsItemSelected(item);
|
||||
|
||||
switch (item.getItemId()) {
|
||||
// TODO / WARNING: R.id values are NON-CONSTANT in Gradle 8.0+ - what would be the best way to address this?! -AL 2024/08/26
|
||||
case R.id.media_preview__overview: showOverview(); return true;
|
||||
case R.id.media_preview__forward: forward(); return true;
|
||||
case R.id.save: saveToDisk(); return true;
|
||||
@@ -537,15 +537,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||
throw new RuntimeException("restartItem = " + restartItem + ", data.second = " + data.second + " leftIsRecent = " + leftIsRecent, e);
|
||||
}
|
||||
|
||||
if (item == 0) {
|
||||
viewPagerListener.onPageSelected(0);
|
||||
}
|
||||
if (item == 0) { viewPagerListener.onPageSelected(0); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(@NonNull Loader<Pair<Cursor, Integer>> loader) {
|
||||
|
||||
}
|
||||
public void onLoaderReset(@NonNull Loader<Pair<Cursor, Integer>> loader) { /* Do nothing */ }
|
||||
|
||||
private class ViewPagerListener implements ViewPager.OnPageChangeListener {
|
||||
|
||||
@@ -580,13 +576,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
|
||||
}
|
||||
public void onPageScrollStateChanged(int state) { /* Do nothing */ }
|
||||
}
|
||||
|
||||
private static class SingleItemPagerAdapter extends MediaItemAdapter {
|
||||
@@ -651,9 +645,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pause(int position) {
|
||||
|
||||
}
|
||||
public void pause(int position) { /* Do nothing */ }
|
||||
|
||||
@Override
|
||||
public @Nullable View getPlaybackControls(int position) {
|
||||
|
@@ -29,12 +29,14 @@ import android.provider.OpenableColumns;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import network.loki.messenger.R;
|
||||
import org.session.libsession.utilities.Address;
|
||||
import org.session.libsession.utilities.DistributionTypes;
|
||||
import org.session.libsession.utilities.ViewUtil;
|
||||
@@ -49,12 +51,6 @@ import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
/**
|
||||
* An activity to quickly share content with contacts
|
||||
*
|
||||
@@ -69,7 +65,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
public static final String EXTRA_ADDRESS_MARSHALLED = "address_marshalled";
|
||||
public static final String EXTRA_DISTRIBUTION_TYPE = "distribution_type";
|
||||
|
||||
|
||||
private ContactSelectionListFragment contactsFragment;
|
||||
private SearchToolbar searchToolbar;
|
||||
private ImageView searchAction;
|
||||
|
@@ -167,7 +167,6 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPlayerError(PlaybackException error) {
|
||||
Log.w(TAG, "MediaPlayer Error: " + error);
|
||||
@@ -206,9 +205,7 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
this.mediaPlayer.release();
|
||||
}
|
||||
|
||||
if (this.audioAttachmentServer != null) {
|
||||
this.audioAttachmentServer.stop();
|
||||
}
|
||||
if (this.audioAttachmentServer != null) { this.audioAttachmentServer.stop(); }
|
||||
|
||||
sensorManager.unregisterListener(AudioSlidePlayer.this);
|
||||
|
||||
@@ -217,9 +214,7 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
}
|
||||
|
||||
public synchronized static void stopAll() {
|
||||
if (playing.isPresent()) {
|
||||
playing.get().stop();
|
||||
}
|
||||
if (playing.isPresent()) { playing.get().stop(); }
|
||||
}
|
||||
|
||||
public synchronized boolean isReady() {
|
||||
@@ -361,9 +356,8 @@ public class AudioSlidePlayer implements SensorEventListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) { /* Do nothing */ }
|
||||
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onPlayerStart(@NonNull AudioSlidePlayer player);
|
||||
|
@@ -44,7 +44,7 @@ public class SwitchPreferenceCompat extends CheckBoxPreference {
|
||||
// Substitute app name into lockscreen preference summary
|
||||
if (key.equalsIgnoreCase(LOCK_SCREEN_KEY)) {
|
||||
Context c = getContext();
|
||||
CharSequence substitutedSummaryCS = Phrase.from(c, R.string.lockAppDescriptionAndroid)
|
||||
CharSequence substitutedSummaryCS = Phrase.from(c, R.string.lockAppDescription)
|
||||
.put(APP_NAME_KEY, c.getString(R.string.app_name))
|
||||
.format();
|
||||
this.setSummary(substitutedSummaryCS);
|
||||
|
@@ -14,7 +14,6 @@ import com.bumptech.glide.RequestManager
|
||||
|
||||
class UserView : LinearLayout {
|
||||
private lateinit var binding: ViewUserBinding
|
||||
var openGroupThreadID: Long = -1L // FIXME: This is a bit ugly
|
||||
|
||||
enum class ActionIndicator {
|
||||
None,
|
||||
@@ -86,8 +85,6 @@ class UserView : LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
fun unbind() {
|
||||
binding.profilePictureView.recycle()
|
||||
}
|
||||
fun unbind() { binding.profilePictureView.recycle() }
|
||||
// endregion
|
||||
}
|
||||
|
@@ -41,7 +41,6 @@ internal class NewMessageViewModel @Inject constructor(
|
||||
override fun onChange(value: String) {
|
||||
loadOnsJob?.cancel()
|
||||
loadOnsJob = null
|
||||
|
||||
_state.update { it.copy(newMessageIdOrOns = value, isTextErrorColor = false, loading = false) }
|
||||
}
|
||||
|
||||
@@ -112,4 +111,4 @@ internal data class State(
|
||||
val isNextButtonEnabled: Boolean get() = newMessageIdOrOns.isNotBlank()
|
||||
}
|
||||
|
||||
internal data class Success(val publicKey: String)
|
||||
internal data class Success(val publicKey: String)
|
@@ -1368,7 +1368,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
return false
|
||||
} else {
|
||||
// ..otherwise if the earliest emoji reaction was more than a minute ago we'll
|
||||
// remove that early reaction to move the timestamp at index 1 into index 0,, add
|
||||
// remove that early reaction to move the timestamp at index 1 into index 0, add
|
||||
// our new timestamp and return true to accept the emoji reaction.
|
||||
emojiRateLimiterQueue.removeFirst()
|
||||
emojiRateLimiterQueue.addLast(timestamp)
|
||||
@@ -1843,7 +1843,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
|
||||
// ..otherwise we can attempt to send the attachment(s).
|
||||
// Note: The only multi-attachment message type is when sending images - all others
|
||||
// attempt send on initial attachment selection.
|
||||
// attempt send the attachment immediately upon file selection.
|
||||
sendAttachments(attachmentManager.buildSlideDeck().asAttachments(), null)
|
||||
}
|
||||
|
||||
@@ -1931,8 +1931,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
} else {
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.RECORD_AUDIO)
|
||||
.withRationaleDialog(getString(R.string.permissionsMicrophoneAccessRequiredAndroid), R.drawable.ic_baseline_mic_48)
|
||||
.withPermanentDenialDialog(Phrase.from(applicationContext, R.string.permissionsMicrophoneAccessRequiredAndroid)
|
||||
.withRationaleDialog(getString(R.string.permissionsMicrophoneAccessRequired), R.drawable.ic_baseline_mic_48)
|
||||
.withPermanentDenialDialog(Phrase.from(applicationContext, R.string.permissionsMicrophoneAccessRequired)
|
||||
.put(APP_NAME_KEY, getString(R.string.app_name))
|
||||
.format().toString())
|
||||
.execute()
|
||||
@@ -2119,7 +2119,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
override fun banUser(messages: Set<MessageRecord>) {
|
||||
showSessionDialog {
|
||||
title(R.string.banUser)
|
||||
// ACL TODO - We need a string for the below `text` element
|
||||
// ACL TODO - We need a string for the below `text` element - have asked Lucy about this 2024/08/26 -AL
|
||||
text("This will ban the selected user from this room. It won't ban them from other rooms.")
|
||||
button(R.string.banUser) { viewModel.banUser(messages.first().individualRecipient); endActionMode() }
|
||||
cancelButton(::endActionMode)
|
||||
@@ -2129,7 +2129,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
override fun banAndDeleteAll(messages: Set<MessageRecord>) {
|
||||
showSessionDialog {
|
||||
title(R.string.banUser)
|
||||
// ACL TODO - We need a string for the below `text` element
|
||||
// ACL TODO - We need a string for the below `text` element - have asked Lucy about this 2024/08/26 -AL
|
||||
text("This will ban the selected user from this room and delete all messages sent by them. It won't ban them from other rooms or delete the messages they sent there.")
|
||||
button(R.string.banUser) { viewModel.banAndDeleteAll(messages.first()); endActionMode() }
|
||||
cancelButton(::endActionMode)
|
||||
|
@@ -33,7 +33,7 @@ class BlockedDialog(private val recipient: Recipient, private val context: Conte
|
||||
|
||||
title(resources.getString(R.string.blockUnblock))
|
||||
text(spannable)
|
||||
dangerButton(R.string.blockUnblock,R.string.AccessibilityId_unblockConfirm) { unblock() }
|
||||
dangerButton(R.string.blockUnblock, R.string.AccessibilityId_unblockConfirm) { unblock() }
|
||||
cancelButton { dismiss() }
|
||||
}
|
||||
|
||||
|
@@ -634,7 +634,7 @@ open class Storage(
|
||||
val threadID = getOrCreateThreadIdFor(Address.fromSerialized(groupId))
|
||||
threadDb.setDate(threadID, formationTimestamp)
|
||||
|
||||
// ACL Note: Commenting out this line prevents the timestamp of room creation being added to a new closed group,
|
||||
// Note: Commenting out this line prevents the timestamp of room creation being added to a new closed group,
|
||||
// which in turn allows us to show the `groupNoMessages` control message text.
|
||||
//insertOutgoingInfoMessage(context, groupId, SignalServiceGroup.Type.CREATION, title, members.map { it.serialize() }, admins.map { it.serialize() }, threadID, formationTimestamp)
|
||||
|
||||
|
@@ -6,17 +6,15 @@ import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.squareup.phrase.Phrase;
|
||||
|
||||
import java.io.File;
|
||||
import net.zetetic.database.sqlcipher.SQLiteConnection;
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase;
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabaseHook;
|
||||
import net.zetetic.database.sqlcipher.SQLiteOpenHelper;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsignal.utilities.Log;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
|
||||
@@ -43,13 +41,8 @@ import org.thoughtcrime.securesms.database.SessionContactDatabase;
|
||||
import org.thoughtcrime.securesms.database.SessionJobDatabase;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
@@ -156,123 +156,10 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
private val isFromOnboarding: Boolean get() = intent.getBooleanExtra(FROM_ONBOARDING, false)
|
||||
private val isNewAccount: Boolean get() = intent.getBooleanExtra(NEW_ACCOUNT, false)
|
||||
|
||||
// ACL REMOVE BLOCK START
|
||||
|
||||
fun getRelativeTimeLocalized(timestampMS: Long): String {
|
||||
// Get the current system time
|
||||
val nowMS = System.currentTimeMillis()
|
||||
|
||||
// Calculate the time difference in milliseconds - this value will be negative if it's in the
|
||||
// future or positive if it's in the past.
|
||||
val timeDifferenceMS = nowMS - timestampMS
|
||||
|
||||
// Choose a desired time resolution based on the time difference.
|
||||
// Note: We do this against the absolute time difference so this function can still work for
|
||||
// both future/past times without having separate future/past cases.
|
||||
val desiredResolution = when (abs(timeDifferenceMS)) {
|
||||
in 0..DateUtils.MINUTE_IN_MILLIS -> DateUtils.SECOND_IN_MILLIS
|
||||
in DateUtils.MINUTE_IN_MILLIS..DateUtils.HOUR_IN_MILLIS -> DateUtils.MINUTE_IN_MILLIS
|
||||
in DateUtils.HOUR_IN_MILLIS..DateUtils.DAY_IN_MILLIS -> DateUtils.HOUR_IN_MILLIS
|
||||
in DateUtils.DAY_IN_MILLIS..DateUtils.WEEK_IN_MILLIS -> DateUtils.DAY_IN_MILLIS
|
||||
|
||||
// We don't do months or years, so if the result is 53 weeks then so be it - also, the
|
||||
// getRelativeTimeSpanString method's resolution maxes out at weeks!
|
||||
else -> DateUtils.WEEK_IN_MILLIS
|
||||
}
|
||||
|
||||
// Use DateUtils to get the relative time span string
|
||||
return DateUtils.getRelativeTimeSpanString(
|
||||
timestampMS,
|
||||
nowMS,
|
||||
desiredResolution,
|
||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||
// Using either DateUtils.FORMAT_ABBREV_RELATIVE or DateUtils.FORMAT_ABBREV_ALL gives:
|
||||
// - 1 sec. ago / 2 sec. ago
|
||||
// - 1 min. ago / 2 min. ago
|
||||
// - 1 hr. ago / 2 hr. ago
|
||||
// - Yesterday / 2 days ago
|
||||
// - August 2 / 2 wk. ago / 14 wk. ago <-- Note: Date running this test is August 9th.
|
||||
|
||||
// Using either 0 or DateUtils.FORMAT_ABBREV_TIME gives:
|
||||
// - 1 second ago / 2 seconds ago
|
||||
// - 1 minute ago / 2 minutes ago
|
||||
// - 1 hour ago / 2 hours ago
|
||||
// - Yesterday / 2 days ago
|
||||
// - August 2nd / 2 weeks ago / 14 weeks ago <-- Note: Date running this test is August 9th.
|
||||
).toString()
|
||||
}
|
||||
|
||||
fun testRelativeTimes(op: (Long, Long) -> Long) {
|
||||
var t = 0L
|
||||
|
||||
// 1 and 2 seconds
|
||||
t = op(System.currentTimeMillis(), 1.seconds.inWholeMilliseconds)
|
||||
Log.w("ACL", "1s -> ${getRelativeTimeLocalized(t)}")
|
||||
t = op(System.currentTimeMillis(), 2.seconds.inWholeMilliseconds)
|
||||
Log.w("ACL", "2s -> ${getRelativeTimeLocalized(t)}")
|
||||
|
||||
// 1 and 2 minutes
|
||||
t = op(System.currentTimeMillis(), 1.minutes.inWholeMilliseconds)
|
||||
Log.w("ACL", "1m -> ${getRelativeTimeLocalized(t)}")
|
||||
t = op(System.currentTimeMillis(), 2.minutes.inWholeMilliseconds)
|
||||
Log.w("ACL", "2m -> ${getRelativeTimeLocalized(t)}")
|
||||
|
||||
// 1 and 2 hours
|
||||
t = op(System.currentTimeMillis(), 1.hours.inWholeMilliseconds)
|
||||
Log.w("ACL", "1h -> ${getRelativeTimeLocalized(t)}")
|
||||
t = op(System.currentTimeMillis(), 2.hours.inWholeMilliseconds)
|
||||
Log.w("ACL", "2h -> ${getRelativeTimeLocalized(t)}")
|
||||
|
||||
// 1 and 2 days
|
||||
t = op(System.currentTimeMillis(), 1.days.inWholeMilliseconds)
|
||||
Log.w("ACL", "1d -> ${getRelativeTimeLocalized(t)}")
|
||||
t = op(System.currentTimeMillis(), 2.days.inWholeMilliseconds)
|
||||
Log.w("ACL", "2d -> ${getRelativeTimeLocalized(t)}")
|
||||
|
||||
// 1 week, 2 weeks, and 100 days (14.285 weeks)
|
||||
t = op(System.currentTimeMillis(), 7.days.inWholeMilliseconds)
|
||||
Log.w("ACL", "1w -> ${getRelativeTimeLocalized(t)}")
|
||||
t = op(System.currentTimeMillis(), 14.days.inWholeMilliseconds)
|
||||
Log.w("ACL", "2w -> ${getRelativeTimeLocalized(t)}")
|
||||
t = op(System.currentTimeMillis(), 100.days.inWholeMilliseconds)
|
||||
Log.w("ACL", "100d -> ${getRelativeTimeLocalized(t)}")
|
||||
}
|
||||
|
||||
fun testSystemGeneratedRelativeTimes() {
|
||||
// Print relative times in the past
|
||||
var op: (Long, Long) -> Long = Long::minus
|
||||
testRelativeTimes(op)
|
||||
|
||||
// Print relative times in the future
|
||||
op = Long::plus
|
||||
testRelativeTimes(op)
|
||||
}
|
||||
|
||||
// ACL REMOVE BLOCK END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// region Lifecycle
|
||||
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
||||
super.onCreate(savedInstanceState, isReady)
|
||||
|
||||
// ACL REMOVE THIS WHEN UNIT TESTS ARE FIXED
|
||||
//Locale.setDefault(Locale.FRENCH)
|
||||
//testSystemGeneratedRelativeTimes()
|
||||
|
||||
// Set content view
|
||||
binding = ActivityHomeBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
@@ -53,7 +53,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
|
||||
setContentView(binding.root)
|
||||
supportActionBar!!.title = resources.getString(R.string.onionRoutingPath)
|
||||
|
||||
// Substitute the localised version of "Session" into the layout
|
||||
// Substitute "Session" into the path description. Note: This is a non-translatable string.
|
||||
val appName = applicationContext.getString(R.string.app_name)
|
||||
val txt = Phrase.from(applicationContext, R.string.onionRoutingPathDescription).put(APP_NAME_KEY, appName).format().toString()
|
||||
binding.pathDescription.text = txt
|
||||
|
@@ -1,10 +1,5 @@
|
||||
package org.thoughtcrime.securesms.linkpreview;
|
||||
|
||||
import static org.thoughtcrime.securesms.giph.util.InfiniteScrollListener.TAG;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
@@ -12,15 +7,9 @@ import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.URLSpan;
|
||||
import android.text.util.Linkify;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.session.libsignal.utilities.Log;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.session.libsignal.utilities.guava.Optional;
|
||||
|
||||
import org.session.libsession.utilities.Util;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
@@ -30,10 +19,10 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import android.text.format.DateFormat;
|
||||
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsignal.utilities.Log;
|
||||
import org.session.libsignal.utilities.guava.Optional;
|
||||
|
||||
public final class LinkPreviewUtil {
|
||||
|
||||
@@ -71,9 +60,9 @@ public final class LinkPreviewUtil {
|
||||
if (linkUrl == null) return false;
|
||||
|
||||
HttpUrl url = HttpUrl.parse(linkUrl);
|
||||
return url != null &&
|
||||
!TextUtils.isEmpty(url.scheme()) &&
|
||||
"https".equals(url.scheme()) &&
|
||||
return url != null &&
|
||||
!TextUtils.isEmpty(url.scheme()) &&
|
||||
"https".equals(url.scheme()) &&
|
||||
isLegalUrl(linkUrl);
|
||||
}
|
||||
|
||||
@@ -84,9 +73,9 @@ public final class LinkPreviewUtil {
|
||||
if (mediaUrl == null) return false;
|
||||
|
||||
HttpUrl url = HttpUrl.parse(mediaUrl);
|
||||
return url != null &&
|
||||
!TextUtils.isEmpty(url.scheme()) &&
|
||||
"https".equals(url.scheme()) &&
|
||||
return url != null &&
|
||||
!TextUtils.isEmpty(url.scheme()) &&
|
||||
"https".equals(url.scheme()) &&
|
||||
isLegalUrl(mediaUrl);
|
||||
}
|
||||
|
||||
|
@@ -35,9 +35,9 @@ class FixedTimeBuckets(
|
||||
@StringRes
|
||||
fun getBucketText(time: ZonedDateTime): Int? {
|
||||
return when {
|
||||
time >= startOfToday -> R.string.BucketedThreadMedia_Today // Should be replaced with call to getLocalisedRelativeDayString
|
||||
time >= startOfYesterday -> R.string.BucketedThreadMedia_Yesterday // Should be replaced with call to getLocalisedRelativeDayString
|
||||
time >= startOfThisWeek -> R.string.attachmentsThisWeek
|
||||
time >= startOfToday -> R.string.BucketedThreadMedia_Today
|
||||
time >= startOfYesterday -> R.string.BucketedThreadMedia_Yesterday
|
||||
time >= startOfThisWeek -> R.string.attachmentsThisWeek
|
||||
time >= startOfThisMonth -> R.string.attachmentsThisMonth
|
||||
else -> null
|
||||
}
|
||||
|
@@ -28,6 +28,8 @@ import android.database.Cursor
|
||||
import android.os.AsyncTask
|
||||
import android.os.Build
|
||||
import android.text.TextUtils
|
||||
import android.widget.Toast
|
||||
import androidx.camera.core.impl.utils.ContextUtil.getApplicationContext
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
@@ -45,6 +47,7 @@ import org.session.libsession.messaging.utilities.AccountId
|
||||
import org.session.libsession.messaging.utilities.SodiumUtilities.blindedKeyPair
|
||||
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
||||
import org.session.libsession.utilities.ServiceUtil
|
||||
import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY
|
||||
import org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY
|
||||
import org.session.libsession.utilities.TextSecurePreferences.Companion.getLocalNumber
|
||||
import org.session.libsession.utilities.TextSecurePreferences.Companion.getNotificationPrivacy
|
||||
@@ -67,6 +70,8 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.ReactionRecord
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||
import org.thoughtcrime.securesms.permissions.Permissions
|
||||
import org.thoughtcrime.securesms.preferences.ShareLogsDialog
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService
|
||||
import org.thoughtcrime.securesms.util.SessionMetaProtocol.canUserReplyToNotification
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
@@ -209,7 +214,6 @@ class DefaultMessageNotifier : MessageNotifier {
|
||||
return
|
||||
}
|
||||
|
||||
//var notificationState: NotificationState
|
||||
try {
|
||||
val notificationState = constructNotificationState(context, telcoCursor)
|
||||
|
||||
@@ -353,7 +357,7 @@ class DefaultMessageNotifier : MessageNotifier {
|
||||
|
||||
val notification = builder.build()
|
||||
|
||||
// ACL FIX THIS PROPERLY
|
||||
// TODO - ACL to fix this properly & will do on 2024-08-26, but just skipping for now so review can start
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
@@ -435,7 +439,7 @@ class DefaultMessageNotifier : MessageNotifier {
|
||||
|
||||
builder.putStringExtra(LATEST_MESSAGE_ID_TAG, messageIdTag)
|
||||
|
||||
// ACL FIX THIS PROPERLY
|
||||
// TODO - ACL to fix this properly & will do on 2024-08-26, but just skipping for now so review can start
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
@@ -463,7 +467,7 @@ class DefaultMessageNotifier : MessageNotifier {
|
||||
val threadDatabase = get(context).threadDatabase()
|
||||
val cache: MutableMap<Long, String?> = HashMap()
|
||||
|
||||
// CAREFUL: Do not put this loop back as `while ((reader.next.also { record = it }) != null) {` because it breaks with a Null Pointer Exception - you have been warned.
|
||||
// CAREFUL: Do not put this loop back as `while ((reader.next.also { record = it }) != null) {` because it breaks with a Null Pointer Exception!
|
||||
var record: MessageRecord? = null
|
||||
do {
|
||||
record = reader.next
|
||||
@@ -587,7 +591,6 @@ class DefaultMessageNotifier : MessageNotifier {
|
||||
if (count == 0) ShortcutBadger.removeCount(context)
|
||||
else ShortcutBadger.applyCount(context, count)
|
||||
} catch (t: Throwable) {
|
||||
// NOTE :: I don't totally trust this thing, so I'm catching everything.
|
||||
Log.w("MessageNotifier", t)
|
||||
}
|
||||
}
|
||||
|
@@ -18,7 +18,6 @@ import java.util.List;
|
||||
import network.loki.messenger.R;
|
||||
import org.session.libsession.messaging.contacts.Contact;
|
||||
import org.session.libsession.utilities.NotificationPrivacyPreference;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsession.utilities.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.database.SessionContactDatabase;
|
||||
@@ -41,12 +40,15 @@ public class MultipleRecipientNotificationBuilder extends AbstractNotificationBu
|
||||
}
|
||||
|
||||
public void setMessageCount(int messageCount, int threadCount) {
|
||||
String txt = Phrase.from(context, R.string.notificationsAndroidSystem)
|
||||
String txt = Phrase.from(context, R.string.notificationsSystem)
|
||||
.put(MESSAGE_COUNT_KEY, messageCount)
|
||||
.put(CONVERSATION_COUNT_KEY, threadCount)
|
||||
.format().toString();
|
||||
setSubText(txt);
|
||||
setContentInfo(String.valueOf(messageCount)); // Note: `setContentInfo` details are only visible in Android API 24 and below - remove when min. API is upgraded.
|
||||
|
||||
// Note: `setContentInfo` details are only visible in Android API 24 and below - as our minimum is now API 26 this can be skipped.
|
||||
//setContentInfo(String.valueOf(messageCount));
|
||||
|
||||
setNumber(messageCount);
|
||||
}
|
||||
|
||||
|
@@ -71,7 +71,7 @@ internal fun MessageNotificationsScreen(
|
||||
|
||||
NotificationRadioButton(
|
||||
R.string.notificationsFastMode,
|
||||
R.string.notificationsFastModeDescriptionAndroid,
|
||||
R.string.notificationsFastModeDescription,
|
||||
modifier = Modifier.contentDescription(R.string.AccessibilityId_notificationsFastMode),
|
||||
tag = R.string.recommended,
|
||||
checked = state.pushEnabled,
|
||||
|
@@ -1,41 +0,0 @@
|
||||
package org.thoughtcrime.securesms.preferences
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsignal.crypto.MnemonicCodec
|
||||
import org.session.libsignal.utilities.hexEncodedPrivateKey
|
||||
import org.thoughtcrime.securesms.createSessionDialog
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
|
||||
|
||||
class SeedDialog: DialogFragment() {
|
||||
private val seed by lazy {
|
||||
val hexEncodedSeed = IdentityKeyUtil.retrieve(requireContext(), IdentityKeyUtil.LOKI_SEED)
|
||||
?: IdentityKeyUtil.getIdentityKeyPair(requireContext()).hexEncodedPrivateKey // Legacy account
|
||||
|
||||
MnemonicCodec { fileName -> MnemonicUtilities.loadFileContents(requireContext(), fileName) }
|
||||
.encode(hexEncodedSeed, MnemonicCodec.Language.Configuration.english)
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||
title(R.string.sessionRecoveryPassword)
|
||||
text(R.string.recoveryPasswordDescription)
|
||||
text(seed, R.style.AccountIdTextView)
|
||||
button(R.string.copy, R.string.AccessibilityId_sessionRecoveryPasswordCopy) { copySeed() }
|
||||
button(R.string.close) { dismiss() }
|
||||
}
|
||||
|
||||
private fun copySeed() {
|
||||
val clipboard = requireActivity().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("Seed", seed)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
Toast.makeText(requireContext(), R.string.copied, Toast.LENGTH_SHORT).show()
|
||||
dismiss()
|
||||
}
|
||||
}
|
@@ -15,6 +15,11 @@ import android.widget.Toast
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.squareup.phrase.Phrase
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.util.Objects
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
import kotlinx.coroutines.Job
|
||||
@@ -29,11 +34,6 @@ import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.createSessionDialog
|
||||
import org.thoughtcrime.securesms.util.FileProviderUtil
|
||||
import org.thoughtcrime.securesms.util.StreamUtil
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.util.Objects
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ShareLogsDialog(private val updateCallback: (Boolean)->Unit): DialogFragment() {
|
||||
|
||||
|
@@ -54,7 +54,7 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
//TODO AC: This service does only serve one purpose now - to track the screen lock state and handle the timer.
|
||||
// TODO: This service does only serve one purpose now - to track the screen lock state and handle the timer.
|
||||
// We need to refactor it and cleanup from all the old Signal code.
|
||||
public class KeyCachingService extends Service {
|
||||
|
||||
@@ -70,7 +70,7 @@ public class KeyCachingService extends Service {
|
||||
|
||||
private final IBinder binder = new KeySetBinder();
|
||||
|
||||
// AC: This is a temporal drop off replacement for the refactoring time being.
|
||||
// This is a temporal drop off replacement for the refactoring time being.
|
||||
// This field only indicates if the app was unlocked or not (null means locked).
|
||||
private static Object masterSecret = null;
|
||||
|
||||
|
@@ -8,21 +8,17 @@ import android.content.Intent;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.squareup.phrase.Phrase;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLDecoder;
|
||||
import network.loki.messenger.R;
|
||||
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||
import org.session.libsession.snode.SnodeAPI;
|
||||
import org.session.libsession.utilities.Address;
|
||||
import org.session.libsignal.utilities.Log;
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender;
|
||||
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
public class QuickResponseService extends IntentService {
|
||||
|
||||
private static final String TAG = QuickResponseService.class.getSimpleName();
|
||||
|
@@ -10,12 +10,14 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.squareup.phrase.Phrase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import network.loki.messenger.R;
|
||||
import org.session.libsession.utilities.FileUtils;
|
||||
import org.session.libsession.utilities.ServiceUtil;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
@@ -24,13 +26,6 @@ import org.session.libsignal.utilities.Log;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.util.FileProviderUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public class UpdateApkReadyListener extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = UpdateApkReadyListener.class.getSimpleName();
|
||||
@@ -128,4 +123,4 @@ public class UpdateApkReadyListener extends BroadcastReceiver {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -31,7 +31,7 @@ import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// Enums used to get the locale-aware String for one of the three relative days
|
||||
public enum class RelativeDay { TODAY, YESTERDAY, TOMORROW }
|
||||
enum class RelativeDay { TODAY, YESTERDAY, TOMORROW }
|
||||
|
||||
/**
|
||||
* Utility methods to help display dates in a nice, easily readable way.
|
||||
@@ -81,30 +81,6 @@ object DateUtils : android.text.format.DateUtils() {
|
||||
FORMAT_SHOW_DATE).toString()
|
||||
}
|
||||
|
||||
// Method to get the locale-aware String for the word "Now"
|
||||
// public fun getLocalisedNowString(): String {
|
||||
// val now = Calendar.getInstance().timeInMillis
|
||||
// return getRelativeTimeSpanString(now, now,MINUTE_IN_MILLIS, FORMAT_SHOW_TIME).toString()
|
||||
// }
|
||||
|
||||
// THIS DOES NOT WORK
|
||||
public fun getLocalisedNowString(): String {
|
||||
|
||||
val now = Calendar.getInstance().timeInMillis
|
||||
val relativeTime = getRelativeTimeSpanString(now, now, MINUTE_IN_MILLIS, FORMAT_SHOW_TIME).toString()
|
||||
|
||||
// Create a DateFormat instance for the current time
|
||||
val timeFormat = getTimeInstance(SHORT, Locale.getDefault())
|
||||
val formattedTime = timeFormat.format(Calendar.getInstance().time)
|
||||
|
||||
// Check if the relative time indicates "0 minutes ago" or similar and replace it with the formatted time
|
||||
return if (relativeTime == "0 minutes ago" || relativeTime == "in 0 minutes") {
|
||||
formattedTime
|
||||
} else {
|
||||
relativeTime
|
||||
}
|
||||
}
|
||||
|
||||
fun getFormattedDateTime(time: Long, template: String, locale: Locale): String {
|
||||
val localizedPattern = getLocalizedPattern(template, locale)
|
||||
return SimpleDateFormat(localizedPattern, locale).format(Date(time))
|
||||
@@ -117,8 +93,9 @@ object DateUtils : android.text.format.DateUtils() {
|
||||
fun getDisplayFormattedTimeSpanString(c: Context, locale: Locale, timestamp: Long): String {
|
||||
// If the timestamp is invalid (ie. 0) then assume we're waiting on data and just use the 'Now' copy
|
||||
return if (timestamp == 0L || isWithin(timestamp, 1, TimeUnit.MINUTES)) {
|
||||
getLocalisedNowString()
|
||||
//c.getString(R.string.DateUtils_just_now) // ACL REMOVE WHEN HAPPY
|
||||
// TODO ACL: We need a string for "Now" because I can't seem to coax a localised version from DateUtils -
|
||||
// TODO: although anyone seeing is this is more than welcome to try! - 2024-08-26
|
||||
"Now"
|
||||
} else if (isToday(timestamp)) {
|
||||
getFormattedDateTime(timestamp, getHourFormat(c), locale)
|
||||
} else if (isWithin(timestamp, 6, TimeUnit.DAYS)) {
|
||||
|
@@ -133,15 +133,9 @@ class SaveAttachmentTask @JvmOverloads constructor(context: Context, count: Int
|
||||
|
||||
private fun createOutputUri(context: Context, outputUri: Uri, contentType: String, fileName: String): Uri? {
|
||||
|
||||
if (fileName == null)
|
||||
{
|
||||
Log.w("ACL", "Filename is null - wtf!")
|
||||
}
|
||||
|
||||
if (fileName != null && fileName.isEmpty())
|
||||
{
|
||||
Log.w("ACL", "Filename is empty - wtf!")
|
||||
}
|
||||
// TODO: This method may pass an empty string as the filename in Android API 28 and below. This requires
|
||||
// TODO: follow-up investigation, but has temporarily been worked around, see:
|
||||
// TODO: https://github.com/oxen-io/session-android/commit/afbb71351a74220c312a09c25cc1c79738453c12
|
||||
|
||||
val fileParts: Array<String> = getFileNameParts(fileName)
|
||||
val base = fileParts[0]
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||
android:key="pref_key_use_fcm"
|
||||
android:title="@string/useFastMode"
|
||||
android:summary="@string/notificationsFastModeDescriptionAndroid"
|
||||
android:summary="@string/notificationsFastModeDescription"
|
||||
android:defaultValue="false" />
|
||||
|
||||
<Preference android:title="@string/notificationsGoToDevice"
|
||||
|
@@ -9,7 +9,7 @@
|
||||
android:key="pref_android_screen_lock"
|
||||
android:defaultValue="false"
|
||||
android:title="@string/lockApp"
|
||||
android:summary="@string/lockAppDescriptionAndroid" />
|
||||
android:summary="@string/lockAppDescription" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||
android:defaultValue="@bool/screen_security_default"
|
||||
|
Reference in New Issue
Block a user