mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 02:55:23 +00:00
Use consistent dialog style
This commit is contained in:
commit
96ec733517
@ -0,0 +1,28 @@
|
|||||||
|
package org.thoughtcrime.securesms
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import network.loki.messenger.R
|
||||||
|
|
||||||
|
class DeleteMediaDialog {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun show(context: Context, recordCount: Int, doDelete: Runnable) = context.showSessionDialog {
|
||||||
|
iconAttribute(R.attr.dialog_alert_icon)
|
||||||
|
title(
|
||||||
|
context.resources.getQuantityString(
|
||||||
|
R.plurals.MediaOverviewActivity_Media_delete_confirm_title,
|
||||||
|
recordCount,
|
||||||
|
recordCount
|
||||||
|
)
|
||||||
|
)
|
||||||
|
text(
|
||||||
|
context.resources.getQuantityString(R.plurals.MediaOverviewActivity_Media_delete_confirm_message,
|
||||||
|
recordCount,
|
||||||
|
recordCount
|
||||||
|
)
|
||||||
|
)
|
||||||
|
button(R.string.delete) { doDelete.run() }
|
||||||
|
cancelButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.thoughtcrime.securesms
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import network.loki.messenger.R
|
||||||
|
|
||||||
|
class DeleteMediaPreviewDialog {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun show(context: Context, doDelete: Runnable) {
|
||||||
|
context.showSessionDialog {
|
||||||
|
iconAttribute(R.attr.dialog_alert_icon)
|
||||||
|
title(R.string.MediaPreviewActivity_media_delete_confirmation_title)
|
||||||
|
text(R.string.MediaPreviewActivity_media_delete_confirmation_message)
|
||||||
|
button(R.string.delete) { doDelete.run() }
|
||||||
|
cancelButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,88 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import org.session.libsession.utilities.ExpirationUtil;
|
|
||||||
|
|
||||||
import cn.carbswang.android.numberpickerview.library.NumberPickerView;
|
|
||||||
import network.loki.messenger.R;
|
|
||||||
|
|
||||||
public class ExpirationDialog extends AlertDialog {
|
|
||||||
|
|
||||||
protected ExpirationDialog(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ExpirationDialog(Context context, int theme) {
|
|
||||||
super(context, theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ExpirationDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
|
|
||||||
super(context, cancelable, cancelListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void show(final Context context,
|
|
||||||
final int currentExpiration,
|
|
||||||
final @NonNull OnClickListener listener)
|
|
||||||
{
|
|
||||||
final View view = createNumberPickerView(context, currentExpiration);
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
||||||
builder.setTitle(context.getString(R.string.ExpirationDialog_disappearing_messages));
|
|
||||||
builder.setView(view);
|
|
||||||
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
|
||||||
int selected = ((NumberPickerView)view.findViewById(R.id.expiration_number_picker)).getValue();
|
|
||||||
listener.onClick(context.getResources().getIntArray(R.array.expiration_times)[selected]);
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
builder.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static View createNumberPickerView(final Context context, final int currentExpiration) {
|
|
||||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
|
||||||
final View view = inflater.inflate(R.layout.expiration_dialog, null);
|
|
||||||
final NumberPickerView numberPickerView = view.findViewById(R.id.expiration_number_picker);
|
|
||||||
final TextView textView = view.findViewById(R.id.expiration_details);
|
|
||||||
final int[] expirationTimes = context.getResources().getIntArray(R.array.expiration_times);
|
|
||||||
final String[] expirationDisplayValues = new String[expirationTimes.length];
|
|
||||||
|
|
||||||
int selectedIndex = expirationTimes.length - 1;
|
|
||||||
|
|
||||||
for (int i=0;i<expirationTimes.length;i++) {
|
|
||||||
expirationDisplayValues[i] = ExpirationUtil.getExpirationDisplayValue(context, expirationTimes[i]);
|
|
||||||
|
|
||||||
if ((currentExpiration >= expirationTimes[i]) &&
|
|
||||||
(i == expirationTimes.length -1 || currentExpiration < expirationTimes[i+1])) {
|
|
||||||
selectedIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
numberPickerView.setDisplayedValues(expirationDisplayValues);
|
|
||||||
numberPickerView.setMinValue(0);
|
|
||||||
numberPickerView.setMaxValue(expirationTimes.length-1);
|
|
||||||
|
|
||||||
NumberPickerView.OnValueChangeListener listener = (picker, oldVal, newVal) -> {
|
|
||||||
if (newVal == 0) {
|
|
||||||
textView.setText(R.string.ExpirationDialog_your_messages_will_not_expire);
|
|
||||||
} else {
|
|
||||||
textView.setText(context.getString(R.string.ExpirationDialog_your_messages_will_disappear_s_after_they_have_been_seen, picker.getDisplayedValues()[newVal]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
numberPickerView.setOnValueChangedListener(listener);
|
|
||||||
numberPickerView.setValue(selectedIndex);
|
|
||||||
listener.onValueChange(numberPickerView, selectedIndex, selectedIndex);
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface OnClickListener {
|
|
||||||
public void onClick(int expirationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,51 @@
|
|||||||
|
package org.thoughtcrime.securesms
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import cn.carbswang.android.numberpickerview.library.NumberPickerView
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsession.utilities.ExpirationUtil
|
||||||
|
|
||||||
|
fun Context.showExpirationDialog(
|
||||||
|
expiration: Int,
|
||||||
|
onExpirationTime: (Int) -> Unit
|
||||||
|
): AlertDialog {
|
||||||
|
val view = LayoutInflater.from(this).inflate(R.layout.expiration_dialog, null)
|
||||||
|
val numberPickerView = view.findViewById<NumberPickerView>(R.id.expiration_number_picker)
|
||||||
|
|
||||||
|
fun updateText(index: Int) {
|
||||||
|
view.findViewById<TextView>(R.id.expiration_details).text = when (index) {
|
||||||
|
0 -> getString(R.string.ExpirationDialog_your_messages_will_not_expire)
|
||||||
|
else -> getString(
|
||||||
|
R.string.ExpirationDialog_your_messages_will_disappear_s_after_they_have_been_seen,
|
||||||
|
numberPickerView.displayedValues[index]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val expirationTimes = resources.getIntArray(R.array.expiration_times)
|
||||||
|
val expirationDisplayValues = expirationTimes
|
||||||
|
.map { ExpirationUtil.getExpirationDisplayValue(this, it) }
|
||||||
|
.toTypedArray()
|
||||||
|
|
||||||
|
val selectedIndex = expirationTimes.run { indexOfFirst { it >= expiration }.coerceIn(indices) }
|
||||||
|
|
||||||
|
numberPickerView.apply {
|
||||||
|
displayedValues = expirationDisplayValues
|
||||||
|
minValue = 0
|
||||||
|
maxValue = expirationTimes.lastIndex
|
||||||
|
setOnValueChangedListener { _, _, index -> updateText(index) }
|
||||||
|
value = selectedIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
updateText(selectedIndex)
|
||||||
|
|
||||||
|
return showSessionDialog {
|
||||||
|
title(getString(R.string.ExpirationDialog_disappearing_messages))
|
||||||
|
view(view)
|
||||||
|
okButton { onExpirationTime(numberPickerView.let { expirationTimes[it.value] }) }
|
||||||
|
cancelButton()
|
||||||
|
}
|
||||||
|
}
|
@ -76,6 +76,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import kotlin.Unit;
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,9 +319,9 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
|
|||||||
@SuppressWarnings("CodeBlock2Expr")
|
@SuppressWarnings("CodeBlock2Expr")
|
||||||
@SuppressLint({"InlinedApi", "StaticFieldLeak"})
|
@SuppressLint({"InlinedApi", "StaticFieldLeak"})
|
||||||
private void handleSaveMedia(@NonNull Collection<MediaDatabase.MediaRecord> mediaRecords) {
|
private void handleSaveMedia(@NonNull Collection<MediaDatabase.MediaRecord> mediaRecords) {
|
||||||
final Context context = getContext();
|
final Context context = requireContext();
|
||||||
|
|
||||||
SaveAttachmentTask.showWarningDialog(context, (dialogInterface, which) -> {
|
SaveAttachmentTask.showWarningDialog(context, mediaRecords.size(), () -> {
|
||||||
Permissions.with(this)
|
Permissions.with(this)
|
||||||
.request(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
.request(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
.maxSdkVersion(Build.VERSION_CODES.P)
|
.maxSdkVersion(Build.VERSION_CODES.P)
|
||||||
@ -362,7 +363,8 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
|
|||||||
}.execute();
|
}.execute();
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
}, mediaRecords.size());
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMediaSavedNotificationIfNeeded() {
|
private void sendMediaSavedNotificationIfNeeded() {
|
||||||
@ -374,25 +376,14 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
|
|||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
private void handleDeleteMedia(@NonNull Collection<MediaDatabase.MediaRecord> mediaRecords) {
|
private void handleDeleteMedia(@NonNull Collection<MediaDatabase.MediaRecord> mediaRecords) {
|
||||||
int recordCount = mediaRecords.size();
|
int recordCount = mediaRecords.size();
|
||||||
Resources res = getContext().getResources();
|
|
||||||
String confirmTitle = res.getQuantityString(R.plurals.MediaOverviewActivity_Media_delete_confirm_title,
|
|
||||||
recordCount,
|
|
||||||
recordCount);
|
|
||||||
String confirmMessage = res.getQuantityString(R.plurals.MediaOverviewActivity_Media_delete_confirm_message,
|
|
||||||
recordCount,
|
|
||||||
recordCount);
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
DeleteMediaDialog.show(
|
||||||
builder.setIconAttribute(R.attr.dialog_alert_icon);
|
requireContext(),
|
||||||
builder.setTitle(confirmTitle);
|
recordCount,
|
||||||
builder.setMessage(confirmMessage);
|
() -> new ProgressDialogAsyncTask<MediaDatabase.MediaRecord, Void, Void>(
|
||||||
builder.setCancelable(true);
|
requireContext(),
|
||||||
|
|
||||||
builder.setPositiveButton(R.string.delete, (dialogInterface, i) -> {
|
|
||||||
new ProgressDialogAsyncTask<MediaDatabase.MediaRecord, Void, Void>(getContext(),
|
|
||||||
R.string.MediaOverviewActivity_Media_delete_progress_title,
|
R.string.MediaOverviewActivity_Media_delete_progress_title,
|
||||||
R.string.MediaOverviewActivity_Media_delete_progress_message)
|
R.string.MediaOverviewActivity_Media_delete_progress_message) {
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(MediaDatabase.MediaRecord... records) {
|
protected Void doInBackground(MediaDatabase.MediaRecord... records) {
|
||||||
if (records == null || records.length == 0) {
|
if (records == null || records.length == 0) {
|
||||||
@ -404,11 +395,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}.execute(mediaRecords.toArray(new MediaDatabase.MediaRecord[mediaRecords.size()])));
|
||||||
}.execute(mediaRecords.toArray(new MediaDatabase.MediaRecord[mediaRecords.size()]));
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSelectAllMedia() {
|
private void handleSelectAllMedia() {
|
||||||
|
@ -85,6 +85,7 @@ import java.io.IOException;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import kotlin.Unit;
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -416,7 +417,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
MediaItem mediaItem = getCurrentMediaItem();
|
MediaItem mediaItem = getCurrentMediaItem();
|
||||||
if (mediaItem == null) return;
|
if (mediaItem == null) return;
|
||||||
|
|
||||||
SaveAttachmentTask.showWarningDialog(this, (dialogInterface, i) -> {
|
SaveAttachmentTask.showWarningDialog(this, 1, () -> {
|
||||||
Permissions.with(this)
|
Permissions.with(this)
|
||||||
.request(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
.request(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
.maxSdkVersion(Build.VERSION_CODES.P)
|
.maxSdkVersion(Build.VERSION_CODES.P)
|
||||||
@ -433,6 +434,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
|
return Unit.INSTANCE;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,29 +451,20 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
DeleteMediaPreviewDialog.show(this, () -> {
|
||||||
builder.setIconAttribute(R.attr.dialog_alert_icon);
|
|
||||||
builder.setTitle(R.string.MediaPreviewActivity_media_delete_confirmation_title);
|
|
||||||
builder.setMessage(R.string.MediaPreviewActivity_media_delete_confirmation_message);
|
|
||||||
builder.setCancelable(true);
|
|
||||||
|
|
||||||
builder.setPositiveButton(R.string.delete, (dialogInterface, which) -> {
|
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... voids) {
|
protected Void doInBackground(Void... voids) {
|
||||||
if (mediaItem.attachment == null) {
|
DatabaseAttachment attachment = mediaItem.attachment;
|
||||||
return null;
|
if (attachment != null) {
|
||||||
|
AttachmentUtil.deleteAttachment(getApplicationContext(), attachment);
|
||||||
}
|
}
|
||||||
AttachmentUtil.deleteAttachment(MediaPreviewActivity.this.getApplicationContext(),
|
|
||||||
mediaItem.attachment);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
|
||||||
|
|
||||||
public class MuteDialog extends AlertDialog {
|
|
||||||
|
|
||||||
|
|
||||||
protected MuteDialog(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MuteDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
|
|
||||||
super(context, cancelable, cancelListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MuteDialog(Context context, int theme) {
|
|
||||||
super(context, theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void show(final Context context, final @NonNull MuteSelectionListener listener) {
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
||||||
builder.setTitle(R.string.MuteDialog_mute_notifications);
|
|
||||||
builder.setItems(R.array.mute_durations, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, final int which) {
|
|
||||||
final long muteUntil;
|
|
||||||
|
|
||||||
switch (which) {
|
|
||||||
case 1: muteUntil = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(2); break;
|
|
||||||
case 2: muteUntil = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1); break;
|
|
||||||
case 3: muteUntil = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(7); break;
|
|
||||||
case 4: muteUntil = Long.MAX_VALUE; break;
|
|
||||||
default: muteUntil = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
listener.onMuted(muteUntil);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.show();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface MuteSelectionListener {
|
|
||||||
public void onMuted(long until);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
27
app/src/main/java/org/thoughtcrime/securesms/MuteDialog.kt
Normal file
27
app/src/main/java/org/thoughtcrime/securesms/MuteDialog.kt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package org.thoughtcrime.securesms
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
fun showMuteDialog(
|
||||||
|
context: Context,
|
||||||
|
onMuteDuration: (Long) -> Unit
|
||||||
|
): AlertDialog = context.showSessionDialog {
|
||||||
|
title(R.string.MuteDialog_mute_notifications)
|
||||||
|
items(Option.values().map { it.stringRes }.map(context::getString).toTypedArray()) {
|
||||||
|
onMuteDuration(Option.values()[it].getTime())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum class Option(@StringRes val stringRes: Int, val getTime: () -> Long) {
|
||||||
|
ONE_HOUR(R.string.arrays__mute_for_one_hour, duration = TimeUnit.HOURS.toMillis(1)),
|
||||||
|
TWO_HOURS(R.string.arrays__mute_for_two_hours, duration = TimeUnit.DAYS.toMillis(2)),
|
||||||
|
ONE_DAY(R.string.arrays__mute_for_one_day, duration = TimeUnit.DAYS.toMillis(1)),
|
||||||
|
SEVEN_DAYS(R.string.arrays__mute_for_seven_days, duration = TimeUnit.DAYS.toMillis(7)),
|
||||||
|
FOREVER(R.string.arrays__mute_forever, getTime = { Long.MAX_VALUE });
|
||||||
|
|
||||||
|
constructor(@StringRes stringRes: Int, duration: Long): this(stringRes, { System.currentTimeMillis() + duration })
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
package org.thoughtcrime.securesms
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.LinearLayout.VERTICAL
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
|
import androidx.annotation.LayoutRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.annotation.StyleRes
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.view.setMargins
|
||||||
|
import androidx.core.view.setPadding
|
||||||
|
import androidx.core.view.updateMargins
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.util.toPx
|
||||||
|
|
||||||
|
|
||||||
|
@DslMarker
|
||||||
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
|
||||||
|
annotation class DialogDsl
|
||||||
|
|
||||||
|
@DialogDsl
|
||||||
|
class SessionDialogBuilder(val context: Context) {
|
||||||
|
|
||||||
|
private val dp20 = toPx(20, context.resources)
|
||||||
|
private val dp40 = toPx(40, context.resources)
|
||||||
|
|
||||||
|
private val dialogBuilder: AlertDialog.Builder = AlertDialog.Builder(context)
|
||||||
|
|
||||||
|
private var dialog: AlertDialog? = null
|
||||||
|
private fun dismiss() = dialog?.dismiss()
|
||||||
|
|
||||||
|
private val topView = LinearLayout(context).apply { orientation = VERTICAL }
|
||||||
|
.also(dialogBuilder::setCustomTitle)
|
||||||
|
private val contentView = LinearLayout(context).apply { orientation = VERTICAL }
|
||||||
|
private val buttonLayout = LinearLayout(context)
|
||||||
|
|
||||||
|
private val root = LinearLayout(context).apply { orientation = VERTICAL }
|
||||||
|
.also(dialogBuilder::setView)
|
||||||
|
.apply {
|
||||||
|
addView(contentView)
|
||||||
|
addView(buttonLayout)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun title(@StringRes id: Int) = title(context.getString(id))
|
||||||
|
|
||||||
|
fun title(text: CharSequence?) = title(text?.toString())
|
||||||
|
fun title(text: String?) {
|
||||||
|
text(text, R.style.TextAppearance_AppCompat_Title) { setPadding(dp20) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun text(@StringRes id: Int, style: Int = 0) = text(context.getString(id), style)
|
||||||
|
fun text(text: CharSequence?, @StyleRes style: Int = 0) {
|
||||||
|
text(text, style) {
|
||||||
|
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||||
|
.apply { updateMargins(dp40, 0, dp40, dp20) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun text(text: CharSequence?, @StyleRes style: Int, modify: TextView.() -> Unit) {
|
||||||
|
text ?: return
|
||||||
|
TextView(context, null, 0, style)
|
||||||
|
.apply {
|
||||||
|
setText(text)
|
||||||
|
textAlignment = View.TEXT_ALIGNMENT_CENTER
|
||||||
|
modify()
|
||||||
|
}.let(topView::addView)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun view(view: View) = contentView.addView(view)
|
||||||
|
|
||||||
|
fun view(@LayoutRes layout: Int): View = LayoutInflater.from(context).inflate(layout, contentView)
|
||||||
|
|
||||||
|
fun iconAttribute(@AttrRes icon: Int): AlertDialog.Builder = dialogBuilder.setIconAttribute(icon)
|
||||||
|
|
||||||
|
fun singleChoiceItems(
|
||||||
|
options: Collection<String>,
|
||||||
|
currentSelected: Int = 0,
|
||||||
|
onSelect: (Int) -> Unit
|
||||||
|
) = singleChoiceItems(options.toTypedArray(), currentSelected, onSelect)
|
||||||
|
|
||||||
|
fun singleChoiceItems(
|
||||||
|
options: Array<String>,
|
||||||
|
currentSelected: Int = 0,
|
||||||
|
onSelect: (Int) -> Unit
|
||||||
|
): AlertDialog.Builder = dialogBuilder.setSingleChoiceItems(
|
||||||
|
options,
|
||||||
|
currentSelected
|
||||||
|
) { dialog, it -> onSelect(it); dialog.dismiss() }
|
||||||
|
|
||||||
|
fun items(
|
||||||
|
options: Array<String>,
|
||||||
|
onSelect: (Int) -> Unit
|
||||||
|
): AlertDialog.Builder = dialogBuilder.setItems(
|
||||||
|
options,
|
||||||
|
) { dialog, it -> onSelect(it); dialog.dismiss() }
|
||||||
|
|
||||||
|
fun destructiveButton(
|
||||||
|
@StringRes text: Int,
|
||||||
|
@StringRes contentDescription: Int,
|
||||||
|
listener: () -> Unit = {}
|
||||||
|
) = button(
|
||||||
|
text,
|
||||||
|
contentDescription,
|
||||||
|
R.style.Widget_Session_Button_Dialog_DestructiveText,
|
||||||
|
listener
|
||||||
|
)
|
||||||
|
|
||||||
|
fun okButton(listener: (() -> Unit) = {}) = button(android.R.string.ok, listener = listener)
|
||||||
|
fun cancelButton(listener: (() -> Unit) = {}) = button(android.R.string.cancel, R.string.AccessibilityId_cancel_button, listener = listener)
|
||||||
|
|
||||||
|
fun button(
|
||||||
|
@StringRes text: Int,
|
||||||
|
@StringRes contentDescriptionRes: Int = text,
|
||||||
|
@StyleRes style: Int = R.style.Widget_Session_Button_Dialog_UnimportantText,
|
||||||
|
listener: (() -> Unit) = {}
|
||||||
|
) = Button(context, null, 0, style).apply {
|
||||||
|
setText(text)
|
||||||
|
contentDescription = resources.getString(contentDescriptionRes)
|
||||||
|
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1f)
|
||||||
|
.apply { setMargins(toPx(20, resources)) }
|
||||||
|
setOnClickListener {
|
||||||
|
listener.invoke()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}.let(buttonLayout::addView)
|
||||||
|
|
||||||
|
fun create(): AlertDialog = dialogBuilder.create().also { dialog = it }
|
||||||
|
fun show(): AlertDialog = dialogBuilder.show().also { dialog = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.showSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
||||||
|
SessionDialogBuilder(this).apply { build() }.show()
|
||||||
|
|
||||||
|
fun Fragment.showSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
||||||
|
SessionDialogBuilder(requireContext()).apply { build() }.show()
|
||||||
|
fun Fragment.createSessionDialog(build: SessionDialogBuilder.() -> Unit): AlertDialog =
|
||||||
|
SessionDialogBuilder(requireContext()).apply { build() }.create()
|
@ -20,8 +20,8 @@ import android.widget.RelativeLayout
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.annotation.DimenRes
|
import androidx.annotation.DimenRes
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -70,7 +70,6 @@ import org.session.libsignal.utilities.Log
|
|||||||
import org.session.libsignal.utilities.guava.Optional
|
import org.session.libsignal.utilities.guava.Optional
|
||||||
import org.session.libsignal.utilities.hexEncodedPrivateKey
|
import org.session.libsignal.utilities.hexEncodedPrivateKey
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.ExpirationDialog
|
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.attachments.ScreenshotObserver
|
import org.thoughtcrime.securesms.attachments.ScreenshotObserver
|
||||||
import org.thoughtcrime.securesms.audio.AudioRecorder
|
import org.thoughtcrime.securesms.audio.AudioRecorder
|
||||||
@ -112,6 +111,8 @@ import org.thoughtcrime.securesms.mms.*
|
|||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
||||||
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
||||||
|
import org.thoughtcrime.securesms.showExpirationDialog
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
import org.thoughtcrime.securesms.util.*
|
import org.thoughtcrime.securesms.util.*
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -406,8 +407,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
push(intent, false)
|
push(intent, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showDialog(baseDialog: BaseDialog, tag: String?) {
|
override fun showDialog(dialogFragment: DialogFragment, tag: String?) {
|
||||||
baseDialog.show(supportFragmentManager, tag)
|
dialogFragment.show(supportFragmentManager, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateLoader(id: Int, bundle: Bundle?): Loader<Cursor> {
|
override fun onCreateLoader(id: Int, bundle: Bundle?): Loader<Cursor> {
|
||||||
@ -965,21 +966,18 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun block(deleteThread: Boolean) {
|
override fun block(deleteThread: Boolean) {
|
||||||
val title = R.string.RecipientPreferenceActivity_block_this_contact_question
|
showSessionDialog {
|
||||||
val message = R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact
|
title(R.string.RecipientPreferenceActivity_block_this_contact_question)
|
||||||
val dialog = AlertDialog.Builder(this)
|
text(R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact)
|
||||||
.setTitle(title)
|
destructiveButton(R.string.RecipientPreferenceActivity_block, R.string.AccessibilityId_block_confirm) {
|
||||||
.setMessage(message)
|
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
|
||||||
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { _, _ ->
|
|
||||||
viewModel.block(this@ConversationActivityV2)
|
viewModel.block(this@ConversationActivityV2)
|
||||||
if (deleteThread) {
|
if (deleteThread) {
|
||||||
viewModel.deleteThread()
|
viewModel.deleteThread()
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}.show()
|
}
|
||||||
val button = dialog.getButton(DialogInterface.BUTTON_POSITIVE)
|
cancelButton()
|
||||||
button.setContentDescription("Confirm block")
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copySessionID(sessionId: String) {
|
override fun copySessionID(sessionId: String) {
|
||||||
@ -1006,28 +1004,27 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
val group = groupDb.getGroup(thread.address.toGroupString()).orNull()
|
val group = groupDb.getGroup(thread.address.toGroupString()).orNull()
|
||||||
if (group?.isActive == false) { return }
|
if (group?.isActive == false) { return }
|
||||||
}
|
}
|
||||||
ExpirationDialog.show(this, thread.expireMessages) { expirationTime: Int ->
|
showExpirationDialog(thread.expireMessages) { expirationTime ->
|
||||||
recipientDb.setExpireMessages(thread, expirationTime)
|
recipientDb.setExpireMessages(thread, expirationTime)
|
||||||
val message = ExpirationTimerUpdate(expirationTime)
|
val message = ExpirationTimerUpdate(expirationTime)
|
||||||
message.recipient = thread.address.serialize()
|
message.recipient = thread.address.serialize()
|
||||||
message.sentTimestamp = SnodeAPI.nowWithOffset
|
message.sentTimestamp = SnodeAPI.nowWithOffset
|
||||||
val expiringMessageManager = ApplicationContext.getInstance(this).expiringMessageManager
|
ApplicationContext.getInstance(this).expiringMessageManager.setExpirationTimer(message)
|
||||||
expiringMessageManager.setExpirationTimer(message)
|
|
||||||
MessageSender.send(message, thread.address)
|
MessageSender.send(message, thread.address)
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unblock() {
|
override fun unblock() {
|
||||||
val title = R.string.ConversationActivity_unblock_this_contact_question
|
showSessionDialog {
|
||||||
val message = R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact
|
title(R.string.ConversationActivity_unblock_this_contact_question)
|
||||||
AlertDialog.Builder(this)
|
text(R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
|
||||||
.setTitle(title)
|
destructiveButton(
|
||||||
.setMessage(message)
|
R.string.ConversationActivity_unblock,
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
R.string.AccessibilityId_block_confirm
|
||||||
.setPositiveButton(R.string.ConversationActivity_unblock) { _, _ ->
|
) { viewModel.unblock(this@ConversationActivityV2) }
|
||||||
viewModel.unblock(this@ConversationActivityV2)
|
cancelButton()
|
||||||
}.show()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `position` is the adapter position; not the visual position
|
// `position` is the adapter position; not the visual position
|
||||||
@ -1468,23 +1465,22 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
private fun showGIFPicker() {
|
private fun showGIFPicker() {
|
||||||
val hasSeenGIFMetaDataWarning: Boolean = textSecurePreferences.hasSeenGIFMetaDataWarning()
|
val hasSeenGIFMetaDataWarning: Boolean = textSecurePreferences.hasSeenGIFMetaDataWarning()
|
||||||
if (!hasSeenGIFMetaDataWarning) {
|
if (!hasSeenGIFMetaDataWarning) {
|
||||||
val builder = AlertDialog.Builder(this)
|
showSessionDialog {
|
||||||
builder.setTitle(R.string.giphy_permission_title)
|
title(R.string.giphy_permission_title)
|
||||||
builder.setMessage(R.string.giphy_permission_message)
|
text(R.string.giphy_permission_message)
|
||||||
builder.setPositiveButton(R.string.continue_2) { dialog: DialogInterface, _: Int ->
|
button(R.string.continue_2) {
|
||||||
textSecurePreferences.setHasSeenGIFMetaDataWarning()
|
textSecurePreferences.setHasSeenGIFMetaDataWarning()
|
||||||
AttachmentManager.selectGif(this, PICK_GIF)
|
selectGif()
|
||||||
dialog.dismiss()
|
|
||||||
}
|
}
|
||||||
builder.setNegativeButton(R.string.cancel) { dialog: DialogInterface, _: Int ->
|
cancelButton()
|
||||||
dialog.dismiss()
|
|
||||||
}
|
}
|
||||||
builder.create().show()
|
|
||||||
} else {
|
} else {
|
||||||
AttachmentManager.selectGif(this, PICK_GIF)
|
selectGif()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun selectGif() = AttachmentManager.selectGif(this, PICK_GIF)
|
||||||
|
|
||||||
private fun showDocumentPicker() {
|
private fun showDocumentPicker() {
|
||||||
AttachmentManager.selectDocument(this, PICK_DOCUMENT)
|
AttachmentManager.selectDocument(this, PICK_DOCUMENT)
|
||||||
}
|
}
|
||||||
@ -1631,35 +1627,23 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
val allHasHash = messages.all { lokiMessageDb.getMessageServerHash(it.id) != null }
|
val allHasHash = messages.all { lokiMessageDb.getMessageServerHash(it.id) != null }
|
||||||
if (recipient.isOpenGroupRecipient) {
|
if (recipient.isOpenGroupRecipient) {
|
||||||
val messageCount = 1
|
val messageCount = 1
|
||||||
val builder = AlertDialog.Builder(this)
|
|
||||||
builder.setTitle(resources.getQuantityString(R.plurals.ConversationFragment_delete_selected_messages, messageCount, messageCount))
|
showSessionDialog {
|
||||||
builder.setMessage(resources.getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messageCount, messageCount))
|
title(resources.getQuantityString(R.plurals.ConversationFragment_delete_selected_messages, messageCount, messageCount))
|
||||||
builder.setCancelable(true)
|
text(resources.getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messageCount, messageCount))
|
||||||
builder.setPositiveButton(R.string.delete) { _, _ ->
|
button(R.string.delete) { messages.forEach(viewModel::deleteForEveryone); endActionMode() }
|
||||||
for (message in messages) {
|
cancelButton { endActionMode() }
|
||||||
viewModel.deleteForEveryone(message)
|
|
||||||
}
|
}
|
||||||
endActionMode()
|
|
||||||
}
|
|
||||||
builder.setNegativeButton(android.R.string.cancel) { dialog, _ ->
|
|
||||||
dialog.dismiss()
|
|
||||||
endActionMode()
|
|
||||||
}
|
|
||||||
builder.show()
|
|
||||||
} else if (allSentByCurrentUser && allHasHash) {
|
} else if (allSentByCurrentUser && allHasHash) {
|
||||||
val bottomSheet = DeleteOptionsBottomSheet()
|
val bottomSheet = DeleteOptionsBottomSheet()
|
||||||
bottomSheet.recipient = recipient
|
bottomSheet.recipient = recipient
|
||||||
bottomSheet.onDeleteForMeTapped = {
|
bottomSheet.onDeleteForMeTapped = {
|
||||||
for (message in messages) {
|
messages.forEach(viewModel::deleteLocally)
|
||||||
viewModel.deleteLocally(message)
|
|
||||||
}
|
|
||||||
bottomSheet.dismiss()
|
bottomSheet.dismiss()
|
||||||
endActionMode()
|
endActionMode()
|
||||||
}
|
}
|
||||||
bottomSheet.onDeleteForEveryoneTapped = {
|
bottomSheet.onDeleteForEveryoneTapped = {
|
||||||
for (message in messages) {
|
messages.forEach(viewModel::deleteForEveryone)
|
||||||
viewModel.deleteForEveryone(message)
|
|
||||||
}
|
|
||||||
bottomSheet.dismiss()
|
bottomSheet.dismiss()
|
||||||
endActionMode()
|
endActionMode()
|
||||||
}
|
}
|
||||||
@ -1670,54 +1654,32 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
bottomSheet.show(supportFragmentManager, bottomSheet.tag)
|
bottomSheet.show(supportFragmentManager, bottomSheet.tag)
|
||||||
} else {
|
} else {
|
||||||
val messageCount = 1
|
val messageCount = 1
|
||||||
val builder = AlertDialog.Builder(this)
|
|
||||||
builder.setTitle(resources.getQuantityString(R.plurals.ConversationFragment_delete_selected_messages, messageCount, messageCount))
|
showSessionDialog {
|
||||||
builder.setMessage(resources.getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messageCount, messageCount))
|
title(resources.getQuantityString(R.plurals.ConversationFragment_delete_selected_messages, messageCount, messageCount))
|
||||||
builder.setCancelable(true)
|
text(resources.getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messageCount, messageCount))
|
||||||
builder.setPositiveButton(R.string.delete) { _, _ ->
|
button(R.string.delete) { messages.forEach(viewModel::deleteLocally); endActionMode() }
|
||||||
for (message in messages) {
|
cancelButton(::endActionMode)
|
||||||
viewModel.deleteLocally(message)
|
|
||||||
}
|
}
|
||||||
endActionMode()
|
|
||||||
}
|
|
||||||
builder.setNegativeButton(android.R.string.cancel) { dialog, _ ->
|
|
||||||
dialog.dismiss()
|
|
||||||
endActionMode()
|
|
||||||
}
|
|
||||||
builder.show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun banUser(messages: Set<MessageRecord>) {
|
override fun banUser(messages: Set<MessageRecord>) {
|
||||||
val builder = AlertDialog.Builder(this)
|
showSessionDialog {
|
||||||
builder.setTitle(R.string.ConversationFragment_ban_selected_user)
|
title(R.string.ConversationFragment_ban_selected_user)
|
||||||
builder.setMessage("This will ban the selected user from this room. It won't ban them from other rooms.")
|
text("This will ban the selected user from this room. It won't ban them from other rooms.")
|
||||||
builder.setCancelable(true)
|
button(R.string.ban) { viewModel.banUser(messages.first().individualRecipient); endActionMode() }
|
||||||
builder.setPositiveButton(R.string.ban) { _, _ ->
|
cancelButton(::endActionMode)
|
||||||
viewModel.banUser(messages.first().individualRecipient)
|
|
||||||
endActionMode()
|
|
||||||
}
|
}
|
||||||
builder.setNegativeButton(android.R.string.cancel) { dialog, _ ->
|
|
||||||
dialog.dismiss()
|
|
||||||
endActionMode()
|
|
||||||
}
|
|
||||||
builder.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun banAndDeleteAll(messages: Set<MessageRecord>) {
|
override fun banAndDeleteAll(messages: Set<MessageRecord>) {
|
||||||
val builder = AlertDialog.Builder(this)
|
showSessionDialog {
|
||||||
builder.setTitle(R.string.ConversationFragment_ban_selected_user)
|
title(R.string.ConversationFragment_ban_selected_user)
|
||||||
builder.setMessage("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.")
|
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.")
|
||||||
builder.setCancelable(true)
|
button(R.string.ban) { viewModel.banAndDeleteAll(messages.first().individualRecipient); endActionMode() }
|
||||||
builder.setPositiveButton(R.string.ban) { _, _ ->
|
cancelButton(::endActionMode)
|
||||||
viewModel.banAndDeleteAll(messages.first().individualRecipient)
|
|
||||||
endActionMode()
|
|
||||||
}
|
}
|
||||||
builder.setNegativeButton(android.R.string.cancel) { dialog, _ ->
|
|
||||||
dialog.dismiss()
|
|
||||||
endActionMode()
|
|
||||||
}
|
|
||||||
builder.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copyMessages(messages: Set<MessageRecord>) {
|
override fun copyMessages(messages: Set<MessageRecord>) {
|
||||||
@ -1781,7 +1743,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
|
|
||||||
override fun saveAttachment(messages: Set<MessageRecord>) {
|
override fun saveAttachment(messages: Set<MessageRecord>) {
|
||||||
val message = messages.first() as MmsMessageRecord
|
val message = messages.first() as MmsMessageRecord
|
||||||
SaveAttachmentTask.showWarningDialog(this, { _, _ ->
|
SaveAttachmentTask.showWarningDialog(this) {
|
||||||
Permissions.with(this)
|
Permissions.with(this)
|
||||||
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
.maxSdkVersion(Build.VERSION_CODES.P)
|
.maxSdkVersion(Build.VERSION_CODES.P)
|
||||||
@ -1809,7 +1771,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
Toast.LENGTH_LONG).show()
|
Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
.execute()
|
.execute()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reply(messages: Set<MessageRecord>) {
|
override fun reply(messages: Set<MessageRecord>) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2
|
package org.thoughtcrime.securesms.conversation.v2
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
@ -31,6 +30,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord
|
|||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
|
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
|
||||||
class ConversationAdapter(
|
class ConversationAdapter(
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -146,17 +146,15 @@ class ConversationAdapter(
|
|||||||
viewHolder.view.bind(message, messageBefore)
|
viewHolder.view.bind(message, messageBefore)
|
||||||
if (message.isCallLog && message.isFirstMissedCall) {
|
if (message.isCallLog && message.isFirstMissedCall) {
|
||||||
viewHolder.view.setOnClickListener {
|
viewHolder.view.setOnClickListener {
|
||||||
AlertDialog.Builder(context)
|
context.showSessionDialog {
|
||||||
.setTitle(R.string.CallNotificationBuilder_first_call_title)
|
title(R.string.CallNotificationBuilder_first_call_title)
|
||||||
.setMessage(R.string.CallNotificationBuilder_first_call_message)
|
text(R.string.CallNotificationBuilder_first_call_message)
|
||||||
.setPositiveButton(R.string.activity_settings_title) { _, _ ->
|
button(R.string.activity_settings_title) {
|
||||||
val intent = Intent(context, PrivacySettingsActivity::class.java)
|
Intent(context, PrivacySettingsActivity::class.java)
|
||||||
context.startActivity(intent)
|
.let(context::startActivity)
|
||||||
}
|
}
|
||||||
.setNeutralButton(R.string.cancel) { d, _ ->
|
cancelButton()
|
||||||
d.dismiss()
|
|
||||||
}
|
}
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
viewHolder.view.setOnClickListener(null)
|
viewHolder.view.setOnClickListener(null)
|
||||||
|
@ -1,42 +1,41 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.app.Dialog
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.style.StyleSpan
|
import android.text.style.StyleSpan
|
||||||
import android.view.LayoutInflater
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.DialogBlockedBinding
|
|
||||||
import org.session.libsession.messaging.contacts.Contact
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import org.thoughtcrime.securesms.createSessionDialog
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
|
|
||||||
/** Shown upon sending a message to a user that's blocked. */
|
/** Shown upon sending a message to a user that's blocked. */
|
||||||
class BlockedDialog(private val recipient: Recipient, private val context: Context) : BaseDialog() {
|
class BlockedDialog(private val recipient: Recipient, private val context: Context) : DialogFragment() {
|
||||||
|
|
||||||
override fun setContentView(builder: AlertDialog.Builder) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
val binding = DialogBlockedBinding.inflate(LayoutInflater.from(requireContext()))
|
|
||||||
val contactDB = DatabaseComponent.get(requireContext()).sessionContactDatabase()
|
val contactDB = DatabaseComponent.get(requireContext()).sessionContactDatabase()
|
||||||
val sessionID = recipient.address.toString()
|
val sessionID = recipient.address.toString()
|
||||||
val contact = contactDB.getContactWithSessionID(sessionID)
|
val contact = contactDB.getContactWithSessionID(sessionID)
|
||||||
val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
|
val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
|
||||||
val title = resources.getString(R.string.dialog_blocked_title, name)
|
|
||||||
binding.blockedTitleTextView.text = title
|
|
||||||
val explanation = resources.getString(R.string.dialog_blocked_explanation, name)
|
val explanation = resources.getString(R.string.dialog_blocked_explanation, name)
|
||||||
val spannable = SpannableStringBuilder(explanation)
|
val spannable = SpannableStringBuilder(explanation)
|
||||||
val startIndex = explanation.indexOf(name)
|
val startIndex = explanation.indexOf(name)
|
||||||
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + name.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + name.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
binding.blockedExplanationTextView.text = spannable
|
|
||||||
binding.cancelButton.setOnClickListener { dismiss() }
|
title(resources.getString(R.string.dialog_blocked_title, name))
|
||||||
binding.unblockButton.setOnClickListener { unblock() }
|
text(spannable)
|
||||||
builder.setView(binding.root)
|
button(R.string.ConversationActivity_unblock) { unblock() }
|
||||||
|
cancelButton { dismiss() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unblock() {
|
private fun unblock() {
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.style.StyleSpan
|
import android.text.style.StyleSpan
|
||||||
import android.view.LayoutInflater
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.DialogDownloadBinding
|
|
||||||
import org.session.libsession.messaging.contacts.Contact
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
import org.session.libsession.messaging.jobs.JobQueue
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import org.thoughtcrime.securesms.createSessionDialog
|
||||||
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -21,25 +21,24 @@ import javax.inject.Inject
|
|||||||
/** Shown when receiving media from a contact for the first time, to confirm that
|
/** Shown when receiving media from a contact for the first time, to confirm that
|
||||||
* they are to be trusted and files sent by them are to be downloaded. */
|
* they are to be trusted and files sent by them are to be downloaded. */
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class DownloadDialog(private val recipient: Recipient) : BaseDialog() {
|
class DownloadDialog(private val recipient: Recipient) : DialogFragment() {
|
||||||
|
|
||||||
@Inject lateinit var contactDB: SessionContactDatabase
|
@Inject lateinit var contactDB: SessionContactDatabase
|
||||||
|
|
||||||
override fun setContentView(builder: AlertDialog.Builder) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
val binding = DialogDownloadBinding.inflate(LayoutInflater.from(requireContext()))
|
|
||||||
val sessionID = recipient.address.toString()
|
val sessionID = recipient.address.toString()
|
||||||
val contact = contactDB.getContactWithSessionID(sessionID)
|
val contact = contactDB.getContactWithSessionID(sessionID)
|
||||||
val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
|
val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
|
||||||
val title = resources.getString(R.string.dialog_download_title, name)
|
title(resources.getString(R.string.dialog_download_title, name))
|
||||||
binding.downloadTitleTextView.text = title
|
|
||||||
val explanation = resources.getString(R.string.dialog_download_explanation, name)
|
val explanation = resources.getString(R.string.dialog_download_explanation, name)
|
||||||
val spannable = SpannableStringBuilder(explanation)
|
val spannable = SpannableStringBuilder(explanation)
|
||||||
val startIndex = explanation.indexOf(name)
|
val startIndex = explanation.indexOf(name)
|
||||||
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + name.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + name.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
binding.downloadExplanationTextView.text = spannable
|
text(spannable)
|
||||||
binding.cancelButton.setOnClickListener { dismiss() }
|
|
||||||
binding.downloadButton.setOnClickListener { trust() }
|
button(R.string.dialog_download_button_title, R.string.AccessibilityId_download_media) { trust() }
|
||||||
builder.setView(binding.root)
|
cancelButton { dismiss() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun trust() {
|
private fun trust() {
|
||||||
|
@ -1,45 +1,41 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.style.StyleSpan
|
import android.text.style.StyleSpan
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.DialogJoinOpenGroupBinding
|
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.utilities.OpenGroupUrlParser
|
import org.session.libsession.utilities.OpenGroupUrlParser
|
||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import org.thoughtcrime.securesms.createSessionDialog
|
||||||
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
|
|
||||||
/** Shown upon tapping an open group invitation. */
|
/** Shown upon tapping an open group invitation. */
|
||||||
class JoinOpenGroupDialog(private val name: String, private val url: String) : BaseDialog() {
|
class JoinOpenGroupDialog(private val name: String, private val url: String) : DialogFragment() {
|
||||||
|
|
||||||
override fun setContentView(builder: AlertDialog.Builder) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
val binding = DialogJoinOpenGroupBinding.inflate(LayoutInflater.from(requireContext()))
|
title(resources.getString(R.string.dialog_join_open_group_title, name))
|
||||||
val title = resources.getString(R.string.dialog_join_open_group_title, name)
|
|
||||||
binding.joinOpenGroupTitleTextView.text = title
|
|
||||||
val explanation = resources.getString(R.string.dialog_join_open_group_explanation, name)
|
val explanation = resources.getString(R.string.dialog_join_open_group_explanation, name)
|
||||||
val spannable = SpannableStringBuilder(explanation)
|
val spannable = SpannableStringBuilder(explanation)
|
||||||
val startIndex = explanation.indexOf(name)
|
val startIndex = explanation.indexOf(name)
|
||||||
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + name.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
spannable.setSpan(StyleSpan(Typeface.BOLD), startIndex, startIndex + name.count(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
binding.joinOpenGroupExplanationTextView.text = spannable
|
text(spannable)
|
||||||
binding.cancelButton.setOnClickListener { dismiss() }
|
cancelButton { dismiss() }
|
||||||
binding.joinButton.setOnClickListener { join() }
|
button(R.string.open_group_invitation_view__join_accessibility_description) { join() }
|
||||||
builder.setView(binding.root)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun join() {
|
private fun join() {
|
||||||
val openGroup = OpenGroupUrlParser.parseUrl(url)
|
val openGroup = OpenGroupUrlParser.parseUrl(url)
|
||||||
val activity = requireContext() as AppCompatActivity
|
val activity = requireActivity()
|
||||||
ThreadUtils.queue {
|
ThreadUtils.queue {
|
||||||
try {
|
try {
|
||||||
OpenGroupManager.add(openGroup.server, openGroup.room, openGroup.serverPublicKey, activity)
|
openGroup.apply { OpenGroupManager.add(server, room, serverPublicKey, activity) }
|
||||||
MessagingModuleConfiguration.shared.storage.onOpenGroupAdded(openGroup.server)
|
MessagingModuleConfiguration.shared.storage.onOpenGroupAdded(openGroup.server)
|
||||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(activity)
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(activity)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.app.Dialog
|
||||||
import androidx.appcompat.app.AlertDialog
|
import android.os.Bundle
|
||||||
import network.loki.messenger.databinding.DialogLinkPreviewBinding
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import org.thoughtcrime.securesms.createSessionDialog
|
||||||
|
|
||||||
/** Shown the first time the user inputs a URL that could generate a link preview, to
|
/** Shown the first time the user inputs a URL that could generate a link preview, to
|
||||||
* let them know that Session offers the ability to send and receive link previews. */
|
* let them know that Session offers the ability to send and receive link previews. */
|
||||||
class LinkPreviewDialog(private val onEnabled: () -> Unit) : BaseDialog() {
|
class LinkPreviewDialog(private val onEnabled: () -> Unit) : DialogFragment() {
|
||||||
|
|
||||||
override fun setContentView(builder: AlertDialog.Builder) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
val binding = DialogLinkPreviewBinding.inflate(LayoutInflater.from(requireContext()))
|
title(R.string.dialog_link_preview_title)
|
||||||
binding.cancelButton.setOnClickListener { dismiss() }
|
text(R.string.dialog_link_preview_explanation)
|
||||||
binding.enableLinkPreviewsButton.setOnClickListener { enable() }
|
button(R.string.dialog_link_preview_enable_button_title) { enable() }
|
||||||
builder.setView(binding.root)
|
cancelButton { dismiss() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun enable() {
|
private fun enable() {
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.app.Dialog
|
||||||
import androidx.appcompat.app.AlertDialog
|
import android.os.Bundle
|
||||||
import network.loki.messenger.databinding.DialogSendSeedBinding
|
import androidx.fragment.app.DialogFragment
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.createSessionDialog
|
||||||
|
|
||||||
/** Shown if the user is about to send their recovery phrase to someone. */
|
/** Shown if the user is about to send their recovery phrase to someone. */
|
||||||
class SendSeedDialog(private val proceed: (() -> Unit)? = null) : BaseDialog() {
|
class SendSeedDialog(private val proceed: (() -> Unit)? = null) : DialogFragment() {
|
||||||
|
|
||||||
override fun setContentView(builder: AlertDialog.Builder) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
val binding = DialogSendSeedBinding.inflate(LayoutInflater.from(requireContext()))
|
title(R.string.dialog_send_seed_title)
|
||||||
binding.cancelButton.setOnClickListener { dismiss() }
|
text(R.string.dialog_send_seed_explanation)
|
||||||
binding.sendSeedButton.setOnClickListener { send() }
|
button(R.string.dialog_send_seed_send_button_title) { send() }
|
||||||
builder.setView(binding.root)
|
cancelButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun send() {
|
private fun send() {
|
||||||
|
@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.conversation.v2.menus
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.PorterDuff
|
import android.graphics.PorterDuff
|
||||||
@ -15,7 +14,6 @@ import android.widget.ImageView
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
@ -34,7 +32,6 @@ import org.session.libsession.utilities.recipients.Recipient
|
|||||||
import org.session.libsignal.utilities.guava.Optional
|
import org.session.libsignal.utilities.guava.Optional
|
||||||
import org.session.libsignal.utilities.toHexString
|
import org.session.libsignal.utilities.toHexString
|
||||||
import org.thoughtcrime.securesms.MediaOverviewActivity
|
import org.thoughtcrime.securesms.MediaOverviewActivity
|
||||||
import org.thoughtcrime.securesms.MuteDialog
|
|
||||||
import org.thoughtcrime.securesms.ShortcutLauncherActivity
|
import org.thoughtcrime.securesms.ShortcutLauncherActivity
|
||||||
import org.thoughtcrime.securesms.calls.WebRtcCallActivity
|
import org.thoughtcrime.securesms.calls.WebRtcCallActivity
|
||||||
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
|
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
|
||||||
@ -45,6 +42,8 @@ import org.thoughtcrime.securesms.groups.EditClosedGroupActivity
|
|||||||
import org.thoughtcrime.securesms.groups.EditClosedGroupActivity.Companion.groupIDKey
|
import org.thoughtcrime.securesms.groups.EditClosedGroupActivity.Companion.groupIDKey
|
||||||
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
|
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
|
||||||
import org.thoughtcrime.securesms.service.WebRtcCallService
|
import org.thoughtcrime.securesms.service.WebRtcCallService
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
import org.thoughtcrime.securesms.showMuteDialog
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil
|
import org.thoughtcrime.securesms.util.BitmapUtil
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
@ -186,29 +185,23 @@ object ConversationMenuHelper {
|
|||||||
private fun call(context: Context, thread: Recipient) {
|
private fun call(context: Context, thread: Recipient) {
|
||||||
|
|
||||||
if (!TextSecurePreferences.isCallNotificationsEnabled(context)) {
|
if (!TextSecurePreferences.isCallNotificationsEnabled(context)) {
|
||||||
val dialog = AlertDialog.Builder(context)
|
context.showSessionDialog {
|
||||||
.setTitle(R.string.ConversationActivity_call_title)
|
title(R.string.ConversationActivity_call_title)
|
||||||
.setMessage(R.string.ConversationActivity_call_prompt)
|
text(R.string.ConversationActivity_call_prompt)
|
||||||
.setPositiveButton(R.string.activity_settings_title) { _, _ ->
|
button(R.string.activity_settings_title, R.string.AccessibilityId_settings) {
|
||||||
val intent = Intent(context, PrivacySettingsActivity::class.java)
|
Intent(context, PrivacySettingsActivity::class.java).let(context::startActivity)
|
||||||
context.startActivity(intent)
|
}
|
||||||
|
cancelButton()
|
||||||
}
|
}
|
||||||
.setNeutralButton(R.string.cancel) { d, _ ->
|
|
||||||
d.dismiss()
|
|
||||||
}.create()
|
|
||||||
dialog.getButton(DialogInterface.BUTTON_POSITIVE)?.contentDescription = context.getString(R.string.AccessibilityId_settings)
|
|
||||||
dialog.getButton(DialogInterface.BUTTON_NEGATIVE)?.contentDescription = context.getString(R.string.AccessibilityId_cancel_button)
|
|
||||||
dialog.show()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val service = WebRtcCallService.createCall(context, thread)
|
WebRtcCallService.createCall(context, thread)
|
||||||
context.startService(service)
|
.let(context::startService)
|
||||||
|
|
||||||
val activity = Intent(context, WebRtcCallActivity::class.java).apply {
|
Intent(context, WebRtcCallActivity::class.java)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
.apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK }
|
||||||
}
|
.let(context::startActivity)
|
||||||
context.startActivity(activity)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,9 +288,7 @@ object ConversationMenuHelper {
|
|||||||
|
|
||||||
private fun leaveClosedGroup(context: Context, thread: Recipient) {
|
private fun leaveClosedGroup(context: Context, thread: Recipient) {
|
||||||
if (!thread.isClosedGroupRecipient) { return }
|
if (!thread.isClosedGroupRecipient) { return }
|
||||||
val builder = AlertDialog.Builder(context)
|
|
||||||
builder.setTitle(context.resources.getString(R.string.ConversationActivity_leave_group))
|
|
||||||
builder.setCancelable(true)
|
|
||||||
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
|
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
|
||||||
val admins = group.admins
|
val admins = group.admins
|
||||||
val sessionID = TextSecurePreferences.getLocalNumber(context)
|
val sessionID = TextSecurePreferences.getLocalNumber(context)
|
||||||
@ -307,29 +298,25 @@ object ConversationMenuHelper {
|
|||||||
} else {
|
} else {
|
||||||
context.resources.getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group)
|
context.resources.getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group)
|
||||||
}
|
}
|
||||||
builder.setMessage(message)
|
|
||||||
builder.setPositiveButton(R.string.yes) { _, _ ->
|
fun onLeaveFailed() = Toast.makeText(context, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show()
|
||||||
var groupPublicKey: String?
|
|
||||||
var isClosedGroup: Boolean
|
context.showSessionDialog {
|
||||||
|
title(R.string.ConversationActivity_leave_group)
|
||||||
|
text(message)
|
||||||
|
button(R.string.yes) {
|
||||||
try {
|
try {
|
||||||
groupPublicKey = doubleDecodeGroupID(thread.address.toString()).toHexString()
|
val groupPublicKey = doubleDecodeGroupID(thread.address.toString()).toHexString()
|
||||||
isClosedGroup = DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(groupPublicKey)
|
val isClosedGroup = DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(groupPublicKey)
|
||||||
} catch (e: IOException) {
|
|
||||||
groupPublicKey = null
|
if (isClosedGroup) MessageSender.leave(groupPublicKey, true)
|
||||||
isClosedGroup = false
|
else onLeaveFailed()
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (isClosedGroup) {
|
|
||||||
MessageSender.leave(groupPublicKey!!, true)
|
|
||||||
} else {
|
|
||||||
Toast.makeText(context, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Toast.makeText(context, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show()
|
onLeaveFailed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.setNegativeButton(R.string.no, null)
|
button(R.string.no)
|
||||||
builder.show()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inviteContacts(context: Context, thread: Recipient) {
|
private fun inviteContacts(context: Context, thread: Recipient) {
|
||||||
@ -344,7 +331,7 @@ object ConversationMenuHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun mute(context: Context, thread: Recipient) {
|
private fun mute(context: Context, thread: Recipient) {
|
||||||
MuteDialog.show(ContextThemeWrapper(context, context.theme)) { until: Long ->
|
showMuteDialog(ContextThemeWrapper(context, context.theme)) { until ->
|
||||||
DatabaseComponent.get(context).recipientDatabase().setMuted(thread, until)
|
DatabaseComponent.get(context).recipientDatabase().setMuted(thread, until)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.utilities
|
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.ColorDrawable
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.fragment.app.DialogFragment
|
|
||||||
import org.thoughtcrime.securesms.util.UiModeUtilities
|
|
||||||
|
|
||||||
open class BaseDialog : DialogFragment() {
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
||||||
val builder = AlertDialog.Builder(requireContext())
|
|
||||||
setContentView(builder)
|
|
||||||
val result = builder.create()
|
|
||||||
result.window?.setDimAmount(0.6f)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun setContentView(builder: AlertDialog.Builder) {
|
|
||||||
// To be overridden by subclasses
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +1,18 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.utilities
|
package org.thoughtcrime.securesms.conversation.v2.utilities
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
|
||||||
object NotificationUtils {
|
object NotificationUtils {
|
||||||
fun showNotifyDialog(context: Context, thread: Recipient, notifyTypeHandler: (Int)->Unit) {
|
fun showNotifyDialog(context: Context, thread: Recipient, notifyTypeHandler: (Int)->Unit) {
|
||||||
val notifyTypes = context.resources.getStringArray(R.array.notify_types)
|
context.showSessionDialog {
|
||||||
val currentSelected = thread.notifyType
|
title(R.string.RecipientPreferenceActivity_notification_settings)
|
||||||
|
singleChoiceItems(
|
||||||
AlertDialog.Builder(context)
|
context.resources.getStringArray(R.array.notify_types),
|
||||||
.setSingleChoiceItems(notifyTypes,currentSelected) { d, newSelection ->
|
thread.notifyType
|
||||||
notifyTypeHandler(newSelection)
|
) { notifyTypeHandler(it) }
|
||||||
d.dismiss()
|
|
||||||
}
|
}
|
||||||
.setTitle(R.string.RecipientPreferenceActivity_notification_settings)
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,7 +10,6 @@ import android.os.Bundle
|
|||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -41,7 +40,6 @@ import org.session.libsignal.utilities.Log
|
|||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
import org.session.libsignal.utilities.toHexString
|
import org.session.libsignal.utilities.toHexString
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.MuteDialog
|
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.conversation.start.NewConversationFragment
|
import org.thoughtcrime.securesms.conversation.start.NewConversationFragment
|
||||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||||
@ -63,6 +61,8 @@ import org.thoughtcrime.securesms.mms.GlideRequests
|
|||||||
import org.thoughtcrime.securesms.onboarding.SeedActivity
|
import org.thoughtcrime.securesms.onboarding.SeedActivity
|
||||||
import org.thoughtcrime.securesms.onboarding.SeedReminderViewDelegate
|
import org.thoughtcrime.securesms.onboarding.SeedReminderViewDelegate
|
||||||
import org.thoughtcrime.securesms.preferences.SettingsActivity
|
import org.thoughtcrime.securesms.preferences.SettingsActivity
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
import org.thoughtcrime.securesms.showMuteDialog
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
import org.thoughtcrime.securesms.util.IP2Country
|
import org.thoughtcrime.securesms.util.IP2Country
|
||||||
@ -488,39 +488,39 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun blockConversation(thread: ThreadRecord) {
|
private fun blockConversation(thread: ThreadRecord) {
|
||||||
AlertDialog.Builder(this)
|
showSessionDialog {
|
||||||
.setTitle(R.string.RecipientPreferenceActivity_block_this_contact_question)
|
title(R.string.RecipientPreferenceActivity_block_this_contact_question)
|
||||||
.setMessage(R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact)
|
text(R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
button(R.string.RecipientPreferenceActivity_block) {
|
||||||
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { dialog, _ ->
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
recipientDatabase.setBlocked(thread.recipient, true)
|
recipientDatabase.setBlocked(thread.recipient, true)
|
||||||
// TODO: Remove in UserConfig branch
|
// TODO: Remove in UserConfig branch
|
||||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@HomeActivity)
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@HomeActivity)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
||||||
dialog.dismiss()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.show()
|
}
|
||||||
|
cancelButton()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unblockConversation(thread: ThreadRecord) {
|
private fun unblockConversation(thread: ThreadRecord) {
|
||||||
AlertDialog.Builder(this)
|
showSessionDialog {
|
||||||
.setTitle(R.string.RecipientPreferenceActivity_unblock_this_contact_question)
|
title(R.string.RecipientPreferenceActivity_unblock_this_contact_question)
|
||||||
.setMessage(R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
|
text(R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
button(R.string.RecipientPreferenceActivity_unblock) {
|
||||||
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock) { dialog, _ ->
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
recipientDatabase.setBlocked(thread.recipient, false)
|
recipientDatabase.setBlocked(thread.recipient, false)
|
||||||
// TODO: Remove in UserConfig branch
|
// TODO: Remove in UserConfig branch
|
||||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@HomeActivity)
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@HomeActivity)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
||||||
dialog.dismiss()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.show()
|
}
|
||||||
|
cancelButton()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setConversationMuted(thread: ThreadRecord, isMuted: Boolean) {
|
private fun setConversationMuted(thread: ThreadRecord, isMuted: Boolean) {
|
||||||
@ -532,7 +532,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MuteDialog.show(this) { until: Long ->
|
showMuteDialog(this) { until ->
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
recipientDatabase.setMuted(thread.recipient, until)
|
recipientDatabase.setMuted(thread.recipient, until)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
@ -578,32 +578,27 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
} else {
|
} else {
|
||||||
resources.getString(R.string.activity_home_delete_conversation_dialog_message)
|
resources.getString(R.string.activity_home_delete_conversation_dialog_message)
|
||||||
}
|
}
|
||||||
val dialog = AlertDialog.Builder(this)
|
|
||||||
dialog.setMessage(message)
|
showSessionDialog {
|
||||||
dialog.setPositiveButton(R.string.yes) { _, _ ->
|
text(message)
|
||||||
|
button(R.string.yes) {
|
||||||
lifecycleScope.launch(Dispatchers.Main) {
|
lifecycleScope.launch(Dispatchers.Main) {
|
||||||
val context = this@HomeActivity as Context
|
val context = this@HomeActivity
|
||||||
// Cancel any outstanding jobs
|
// Cancel any outstanding jobs
|
||||||
DatabaseComponent.get(context).sessionJobDatabase().cancelPendingMessageSendJobs(threadID)
|
DatabaseComponent.get(context).sessionJobDatabase().cancelPendingMessageSendJobs(threadID)
|
||||||
// Send a leave group message if this is an active closed group
|
// Send a leave group message if this is an active closed group
|
||||||
if (recipient.address.isClosedGroup && DatabaseComponent.get(context).groupDatabase().isActive(recipient.address.toGroupString())) {
|
if (recipient.address.isClosedGroup && DatabaseComponent.get(context).groupDatabase().isActive(recipient.address.toGroupString())) {
|
||||||
var isClosedGroup: Boolean
|
|
||||||
var groupPublicKey: String?
|
|
||||||
try {
|
try {
|
||||||
groupPublicKey = GroupUtil.doubleDecodeGroupID(recipient.address.toString()).toHexString()
|
GroupUtil.doubleDecodeGroupID(recipient.address.toString()).toHexString()
|
||||||
isClosedGroup = DatabaseComponent.get(context).lokiAPIDatabase().isClosedGroup(groupPublicKey)
|
.takeIf(DatabaseComponent.get(context).lokiAPIDatabase()::isClosedGroup)
|
||||||
} catch (e: IOException) {
|
?.let { MessageSender.explicitLeave(it, false) }
|
||||||
groupPublicKey = null
|
} catch (_: IOException) {
|
||||||
isClosedGroup = false
|
|
||||||
}
|
|
||||||
if (isClosedGroup) {
|
|
||||||
MessageSender.explicitLeave(groupPublicKey!!, false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete the conversation
|
// Delete the conversation
|
||||||
val v2OpenGroup = DatabaseComponent.get(this@HomeActivity).lokiThreadDatabase().getOpenGroupChat(threadID)
|
val v2OpenGroup = DatabaseComponent.get(context).lokiThreadDatabase().getOpenGroupChat(threadID)
|
||||||
if (v2OpenGroup != null) {
|
if (v2OpenGroup != null) {
|
||||||
OpenGroupManager.delete(v2OpenGroup.server, v2OpenGroup.room, this@HomeActivity)
|
v2OpenGroup.apply { OpenGroupManager.delete(server, room, context) }
|
||||||
} else {
|
} else {
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
threadDb.deleteConversation(threadID)
|
threadDb.deleteConversation(threadID)
|
||||||
@ -616,10 +611,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
Toast.makeText(context, toastMessage, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, toastMessage, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dialog.setNegativeButton(R.string.no) { _, _ ->
|
button(R.string.no)
|
||||||
// Do nothing
|
|
||||||
}
|
}
|
||||||
dialog.create().show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openSettings() {
|
private fun openSettings() {
|
||||||
@ -633,17 +626,15 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun hideMessageRequests() {
|
private fun hideMessageRequests() {
|
||||||
AlertDialog.Builder(this)
|
showSessionDialog {
|
||||||
.setMessage("Hide message requests?")
|
text("Hide message requests?")
|
||||||
.setPositiveButton(R.string.yes) { _, _ ->
|
button(R.string.yes) {
|
||||||
textSecurePreferences.setHasHiddenMessageRequests()
|
textSecurePreferences.setHasHiddenMessageRequests()
|
||||||
setupMessageRequestsBanner()
|
setupMessageRequestsBanner()
|
||||||
homeViewModel.tryUpdateChannel()
|
homeViewModel.tryUpdateChannel()
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.no) { _, _ ->
|
button(R.string.no)
|
||||||
// Do nothing
|
|
||||||
}
|
}
|
||||||
.create().show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showNewConversation() {
|
private fun showNewConversation() {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.thoughtcrime.securesms.messagerequests
|
package org.thoughtcrime.securesms.messagerequests
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@ -20,6 +19,7 @@ import org.thoughtcrime.securesms.database.ThreadDatabase
|
|||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
import org.thoughtcrime.securesms.util.push
|
import org.thoughtcrime.securesms.util.push
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -77,34 +77,34 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBlockConversationClick(thread: ThreadRecord) {
|
override fun onBlockConversationClick(thread: ThreadRecord) {
|
||||||
val dialog = AlertDialog.Builder(this)
|
fun doBlock() {
|
||||||
dialog.setTitle(R.string.RecipientPreferenceActivity_block_this_contact_question)
|
|
||||||
.setMessage(R.string.message_requests_block_message)
|
|
||||||
.setPositiveButton(R.string.recipient_preferences__block) { _, _ ->
|
|
||||||
viewModel.blockMessageRequest(thread)
|
viewModel.blockMessageRequest(thread)
|
||||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.no) { _, _ ->
|
|
||||||
// Do nothing
|
showSessionDialog {
|
||||||
|
title(R.string.RecipientPreferenceActivity_block_this_contact_question)
|
||||||
|
text(R.string.message_requests_block_message)
|
||||||
|
button(R.string.recipient_preferences__block) { doBlock() }
|
||||||
|
button(R.string.no)
|
||||||
}
|
}
|
||||||
dialog.create().show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeleteConversationClick(thread: ThreadRecord) {
|
override fun onDeleteConversationClick(thread: ThreadRecord) {
|
||||||
val dialog = AlertDialog.Builder(this)
|
fun doDecline() {
|
||||||
dialog.setTitle(R.string.decline)
|
|
||||||
.setMessage(resources.getString(R.string.message_requests_decline_message))
|
|
||||||
.setPositiveButton(R.string.decline) { _,_ ->
|
|
||||||
viewModel.deleteMessageRequest(thread)
|
viewModel.deleteMessageRequest(thread)
|
||||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@MessageRequestsActivity)
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@MessageRequestsActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.no) { _, _ ->
|
|
||||||
// Do nothing
|
showSessionDialog {
|
||||||
|
title(R.string.decline)
|
||||||
|
text(resources.getString(R.string.message_requests_decline_message))
|
||||||
|
button(R.string.decline) { doDecline() }
|
||||||
|
button(R.string.no)
|
||||||
}
|
}
|
||||||
dialog.create().show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateEmptyState() {
|
private fun updateEmptyState() {
|
||||||
@ -114,18 +114,18 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteAllAndBlock() {
|
private fun deleteAllAndBlock() {
|
||||||
val dialog = AlertDialog.Builder(this)
|
fun doDeleteAllAndBlock() {
|
||||||
dialog.setMessage(resources.getString(R.string.message_requests_clear_all_message))
|
|
||||||
dialog.setPositiveButton(R.string.yes) { _, _ ->
|
|
||||||
viewModel.clearAllMessageRequests()
|
viewModel.clearAllMessageRequests()
|
||||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@MessageRequestsActivity)
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@MessageRequestsActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dialog.setNegativeButton(R.string.no) { _, _ ->
|
|
||||||
// Do nothing
|
showSessionDialog {
|
||||||
|
text(resources.getString(R.string.message_requests_clear_all_message))
|
||||||
|
button(R.string.yes) { doDeleteAllAndBlock() }
|
||||||
|
button(R.string.no)
|
||||||
}
|
}
|
||||||
dialog.create().show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.onboarding
|
|||||||
|
|
||||||
import android.animation.ArgbEvaluator
|
import android.animation.ArgbEvaluator
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.TransitionDrawable
|
import android.graphics.drawable.TransitionDrawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -20,6 +19,7 @@ import org.session.libsession.utilities.ThemeUtil
|
|||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||||
import org.thoughtcrime.securesms.home.HomeActivity
|
import org.thoughtcrime.securesms.home.HomeActivity
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
||||||
import org.thoughtcrime.securesms.util.PNModeView
|
import org.thoughtcrime.securesms.util.PNModeView
|
||||||
import org.thoughtcrime.securesms.util.disableClipping
|
import org.thoughtcrime.securesms.util.disableClipping
|
||||||
@ -151,12 +151,13 @@ class PNModeActivity : BaseActionBarActivity() {
|
|||||||
|
|
||||||
private fun register() {
|
private fun register() {
|
||||||
if (selectedOptionView == null) {
|
if (selectedOptionView == null) {
|
||||||
val dialog = AlertDialog.Builder(this)
|
showSessionDialog {
|
||||||
dialog.setTitle(R.string.activity_pn_mode_no_option_picked_dialog_title)
|
title(R.string.activity_pn_mode_no_option_picked_dialog_title)
|
||||||
dialog.setPositiveButton(R.string.ok) { _, _ -> }
|
button(R.string.ok)
|
||||||
dialog.create().show()
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == binding.fcmOptionView))
|
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == binding.fcmOptionView))
|
||||||
val application = ApplicationContext.getInstance(this)
|
val application = ApplicationContext.getInstance(this)
|
||||||
application.startPollingIfNeeded()
|
application.startPollingIfNeeded()
|
||||||
|
@ -162,15 +162,13 @@ public class Permissions {
|
|||||||
request.onResult(requestedPermissions, grantResults, new boolean[requestedPermissions.length]);
|
request.onResult(requestedPermissions, grantResults, new boolean[requestedPermissions.length]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
private void executePermissionsRequestWithRationale(PermissionsRequest request) {
|
private void executePermissionsRequestWithRationale(PermissionsRequest request) {
|
||||||
AlertDialog dialog = RationaleDialog.createFor(permissionObject.getContext(), rationaleDialogMessage, rationalDialogHeader)
|
RationaleDialog.show(
|
||||||
.setPositiveButton(R.string.Permissions_continue, (d, which) -> executePermissionsRequest(request))
|
permissionObject.getContext(),
|
||||||
.setNegativeButton(R.string.Permissions_not_now, (d, which) -> executeNoPermissionsRequest(request))
|
rationaleDialogMessage,
|
||||||
.show();
|
() -> executePermissionsRequest(request),
|
||||||
dialog.getWindow().setLayout((int)(permissionObject.getWindowWidth() * .75), ViewGroup.LayoutParams.WRAP_CONTENT);
|
() -> executeNoPermissionsRequest(request),
|
||||||
Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
rationalDialogHeader);
|
||||||
positiveButton.setContentDescription("Continue");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executePermissionsRequest(PermissionsRequest request) {
|
private void executePermissionsRequest(PermissionsRequest request) {
|
||||||
@ -257,7 +255,7 @@ public class Permissions {
|
|||||||
resultListener.onResult(permissions, grantResults, shouldShowRationaleDialog);
|
resultListener.onResult(permissions, grantResults, shouldShowRationaleDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Intent getApplicationSettingsIntent(@NonNull Context context) {
|
static Intent getApplicationSettingsIntent(@NonNull Context context) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
Uri uri = Uri.fromParts("package", context.getPackageName(), null);
|
Uri uri = Uri.fromParts("package", context.getPackageName(), null);
|
||||||
@ -354,20 +352,8 @@ public class Permissions {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Context context = this.context.get();
|
Context context = this.context.get();
|
||||||
|
if (context == null) return;
|
||||||
if (context != null) {
|
SettingsDialog.show(context, message);
|
||||||
AlertDialog alertDialog = new AlertDialog.Builder(context, R.style.ThemeOverlay_Session_AlertDialog)
|
|
||||||
.setTitle(R.string.Permissions_permission_required)
|
|
||||||
.setMessage(message)
|
|
||||||
.setPositiveButton(R.string.Permissions_continue, (dialog, which) -> context.startActivity(getApplicationSettingsIntent(context)))
|
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
|
||||||
.create();
|
|
||||||
Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
|
||||||
if (positiveButton != null) {
|
|
||||||
positiveButton.setContentDescription(context.getString(R.string.AccessibilityId_continue));
|
|
||||||
}
|
|
||||||
alertDialog.show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.permissions;
|
|
||||||
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout.LayoutParams;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import org.session.libsession.utilities.ViewUtil;
|
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
|
||||||
|
|
||||||
public class RationaleDialog {
|
|
||||||
|
|
||||||
public static AlertDialog.Builder createFor(@NonNull Context context, @NonNull String message, @DrawableRes int... drawables) {
|
|
||||||
View view = LayoutInflater.from(context).inflate(R.layout.permissions_rationale_dialog, null);
|
|
||||||
view.setClipToOutline(true);
|
|
||||||
ViewGroup header = view.findViewById(R.id.header_container);
|
|
||||||
TextView text = view.findViewById(R.id.message);
|
|
||||||
|
|
||||||
for (int i=0;i<drawables.length;i++) {
|
|
||||||
ImageView imageView = new ImageView(context);
|
|
||||||
imageView.setImageDrawable(context.getResources().getDrawable(drawables[i]));
|
|
||||||
imageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
|
|
||||||
|
|
||||||
header.addView(imageView);
|
|
||||||
|
|
||||||
if (i != drawables.length - 1) {
|
|
||||||
TextView plus = new TextView(context);
|
|
||||||
plus.setText("+");
|
|
||||||
plus.setTextSize(TypedValue.COMPLEX_UNIT_SP, 40);
|
|
||||||
plus.setTextColor(Color.WHITE);
|
|
||||||
|
|
||||||
LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
|
||||||
layoutParams.setMargins(ViewUtil.dpToPx(context, 20), 0, ViewUtil.dpToPx(context, 20), 0);
|
|
||||||
|
|
||||||
plus.setLayoutParams(layoutParams);
|
|
||||||
header.addView(plus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
text.setText(message);
|
|
||||||
|
|
||||||
return new AlertDialog.Builder(context, R.style.ThemeOverlay_Session_AlertDialog).setView(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,60 @@
|
|||||||
|
package org.thoughtcrime.securesms.permissions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsession.utilities.ViewUtil
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
|
||||||
|
object RationaleDialog {
|
||||||
|
@JvmStatic
|
||||||
|
fun show(
|
||||||
|
context: Context,
|
||||||
|
message: String,
|
||||||
|
onPositive: Runnable,
|
||||||
|
onNegative: Runnable,
|
||||||
|
@DrawableRes vararg drawables: Int
|
||||||
|
): AlertDialog {
|
||||||
|
val view = LayoutInflater.from(context).inflate(R.layout.permissions_rationale_dialog, null)
|
||||||
|
.apply { clipToOutline = true }
|
||||||
|
val header = view.findViewById<ViewGroup>(R.id.header_container)
|
||||||
|
view.findViewById<TextView>(R.id.message).text = message
|
||||||
|
|
||||||
|
fun addIcon(id: Int) {
|
||||||
|
ImageView(context).apply {
|
||||||
|
setImageDrawable(ResourcesCompat.getDrawable(context.resources, id, context.theme))
|
||||||
|
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
|
||||||
|
}.also(header::addView)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addPlus() {
|
||||||
|
TextView(context).apply {
|
||||||
|
text = "+"
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_SP, 40f)
|
||||||
|
setTextColor(Color.WHITE)
|
||||||
|
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
|
||||||
|
ViewUtil.dpToPx(context, 20).let { setMargins(it, 0, it, 0) }
|
||||||
|
}
|
||||||
|
}.also(header::addView)
|
||||||
|
}
|
||||||
|
|
||||||
|
drawables.firstOrNull()?.let(::addIcon)
|
||||||
|
drawables.drop(1).forEach { addPlus(); addIcon(it) }
|
||||||
|
|
||||||
|
return context.showSessionDialog {
|
||||||
|
view(view)
|
||||||
|
button(R.string.Permissions_continue) { onPositive.run() }
|
||||||
|
button(R.string.Permissions_not_now) { onNegative.run() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.thoughtcrime.securesms.permissions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
|
||||||
|
class SettingsDialog {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun show(context: Context, message: String) {
|
||||||
|
context.showSessionDialog {
|
||||||
|
title(R.string.Permissions_permission_required)
|
||||||
|
text(message)
|
||||||
|
button(R.string.Permissions_continue, R.string.AccessibilityId_continue) {
|
||||||
|
context.startActivity(Permissions.getApplicationSettingsIntent(context))
|
||||||
|
}
|
||||||
|
cancelButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package org.thoughtcrime.securesms.preferences
|
package org.thoughtcrime.securesms.preferences
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
@ -8,6 +7,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ActivityBlockedContactsBinding
|
import network.loki.messenger.databinding.ActivityBlockedContactsBinding
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class BlockedContactsActivity: PassphraseRequiredActionBarActivity() {
|
class BlockedContactsActivity: PassphraseRequiredActionBarActivity() {
|
||||||
@ -19,17 +19,12 @@ class BlockedContactsActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
val adapter: BlockedContactsAdapter by lazy { BlockedContactsAdapter(viewModel) }
|
val adapter: BlockedContactsAdapter by lazy { BlockedContactsAdapter(viewModel) }
|
||||||
|
|
||||||
fun unblock() {
|
fun unblock() {
|
||||||
// show dialog
|
showSessionDialog {
|
||||||
val title = viewModel.getTitle(this)
|
title(viewModel.getTitle(this@BlockedContactsActivity))
|
||||||
|
text(viewModel.getMessage(this@BlockedContactsActivity))
|
||||||
val message = viewModel.getMessage(this)
|
button(R.string.continue_2) { viewModel.unblock(this@BlockedContactsActivity) }
|
||||||
|
cancelButton()
|
||||||
AlertDialog.Builder(this)
|
}
|
||||||
.setTitle(title)
|
|
||||||
.setMessage(message)
|
|
||||||
.setPositiveButton(R.string.continue_2) { _, _ -> viewModel.unblock(this@BlockedContactsActivity) }
|
|
||||||
.setNegativeButton(R.string.cancel) { _, _ -> }
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
||||||
@ -51,4 +46,3 @@ class BlockedContactsActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
package org.thoughtcrime.securesms.preferences
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
|
import org.session.libsession.utilities.TextSecurePreferences.Companion.setBooleanPreference
|
||||||
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
|
||||||
|
internal class CallToggleListener(
|
||||||
|
private val context: Fragment,
|
||||||
|
private val setCallback: (Boolean) -> Unit
|
||||||
|
) : Preference.OnPreferenceChangeListener {
|
||||||
|
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||||
|
if (newValue == false) return true
|
||||||
|
|
||||||
|
// check if we've shown the info dialog and check for microphone permissions
|
||||||
|
context.showSessionDialog {
|
||||||
|
title(R.string.dialog_voice_video_title)
|
||||||
|
text(R.string.dialog_voice_video_message)
|
||||||
|
button(R.string.dialog_link_preview_enable_button_title, R.string.AccessibilityId_enable) { requestMicrophonePermission() }
|
||||||
|
cancelButton()
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun requestMicrophonePermission() {
|
||||||
|
Permissions.with(context)
|
||||||
|
.request(Manifest.permission.RECORD_AUDIO)
|
||||||
|
.onAllGranted {
|
||||||
|
setBooleanPreference(
|
||||||
|
context.requireContext(),
|
||||||
|
TextSecurePreferences.CALL_NOTIFICATIONS_ENABLED,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
setCallback(true)
|
||||||
|
}
|
||||||
|
.onAnyDenied { setCallback(false) }
|
||||||
|
.execute()
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.preferences
|
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.fragment.app.DialogFragment
|
|
||||||
|
|
||||||
class ChangeUiModeDialog : DialogFragment() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TAG = "ChangeUiModeDialog"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
||||||
val context = requireContext()
|
|
||||||
return android.app.AlertDialog.Builder(context)
|
|
||||||
.setTitle("TODO: remove this")
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +1,12 @@
|
|||||||
package org.thoughtcrime.securesms.preferences
|
package org.thoughtcrime.securesms.preferences
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import androidx.appcompat.app.AlertDialog
|
import android.view.View
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -15,10 +18,10 @@ import network.loki.messenger.databinding.DialogClearAllDataBinding
|
|||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import org.thoughtcrime.securesms.createSessionDialog
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
|
|
||||||
class ClearAllDataDialog : BaseDialog() {
|
class ClearAllDataDialog : DialogFragment() {
|
||||||
private lateinit var binding: DialogClearAllDataBinding
|
private lateinit var binding: DialogClearAllDataBinding
|
||||||
|
|
||||||
enum class Steps {
|
enum class Steps {
|
||||||
@ -35,7 +38,11 @@ class ClearAllDataDialog : BaseDialog() {
|
|||||||
updateUI()
|
updateUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setContentView(builder: AlertDialog.Builder) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
|
view(createView())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createView(): View {
|
||||||
binding = DialogClearAllDataBinding.inflate(LayoutInflater.from(requireContext()))
|
binding = DialogClearAllDataBinding.inflate(LayoutInflater.from(requireContext()))
|
||||||
val device = RadioOption("deviceOnly", requireContext().getString(R.string.dialog_clear_all_data_clear_device_only))
|
val device = RadioOption("deviceOnly", requireContext().getString(R.string.dialog_clear_all_data_clear_device_only))
|
||||||
val network = RadioOption("deviceAndNetwork", requireContext().getString(R.string.dialog_clear_all_data_clear_device_and_network))
|
val network = RadioOption("deviceAndNetwork", requireContext().getString(R.string.dialog_clear_all_data_clear_device_and_network))
|
||||||
@ -62,8 +69,7 @@ class ClearAllDataDialog : BaseDialog() {
|
|||||||
Steps.DELETING -> { /* do nothing intentionally */ }
|
Steps.DELETING -> { /* do nothing intentionally */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.setView(binding.root)
|
return binding.root
|
||||||
builder.setCancelable(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateUI() {
|
private fun updateUI() {
|
||||||
|
@ -1,41 +1,24 @@
|
|||||||
package org.thoughtcrime.securesms.preferences
|
package org.thoughtcrime.securesms.preferences
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import network.loki.messenger.databinding.DialogListPreferenceBinding
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
|
||||||
fun listPreferenceDialog(
|
fun listPreferenceDialog(
|
||||||
context: Context,
|
context: Context,
|
||||||
listPreference: ListPreference,
|
listPreference: ListPreference,
|
||||||
dialogListener: () -> Unit
|
onChange: () -> Unit
|
||||||
) : AlertDialog {
|
) : AlertDialog = listPreference.run {
|
||||||
|
context.showSessionDialog {
|
||||||
|
val index = entryValues.indexOf(value)
|
||||||
|
val options = entries.map(CharSequence::toString).toTypedArray()
|
||||||
|
|
||||||
val builder = AlertDialog.Builder(context)
|
title(dialogTitle)
|
||||||
|
text(dialogMessage)
|
||||||
val binding = DialogListPreferenceBinding.inflate(LayoutInflater.from(context))
|
singleChoiceItems(options, index) {
|
||||||
binding.titleTextView.text = listPreference.dialogTitle
|
listPreference.setValueIndex(it)
|
||||||
binding.messageTextView.text = listPreference.dialogMessage
|
onChange()
|
||||||
|
|
||||||
builder.setView(binding.root)
|
|
||||||
|
|
||||||
val dialog = builder.show()
|
|
||||||
|
|
||||||
val valueIndex = listPreference.findIndexOfValue(listPreference.value)
|
|
||||||
RadioOptionAdapter(valueIndex) {
|
|
||||||
listPreference.value = it.value
|
|
||||||
dialog.dismiss()
|
|
||||||
dialogListener()
|
|
||||||
}
|
}
|
||||||
.apply {
|
|
||||||
listPreference.entryValues.zip(listPreference.entries) { value, title ->
|
|
||||||
RadioOption(value.toString(), title.toString())
|
|
||||||
}.let(this::submitList)
|
|
||||||
}
|
}
|
||||||
.let { binding.recyclerView.adapter = it }
|
|
||||||
|
|
||||||
binding.closeButton.setOnClickListener { dialog.dismiss() }
|
|
||||||
|
|
||||||
return dialog
|
|
||||||
}
|
}
|
||||||
|
@ -1,203 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.preferences;
|
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.KeyguardManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.view.ContextThemeWrapper;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
|
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
|
||||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
|
||||||
import org.thoughtcrime.securesms.util.CallNotificationBuilder;
|
|
||||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
|
||||||
|
|
||||||
import kotlin.jvm.functions.Function1;
|
|
||||||
import network.loki.messenger.BuildConfig;
|
|
||||||
import network.loki.messenger.R;
|
|
||||||
|
|
||||||
public class PrivacySettingsPreferenceFragment extends ListSummaryPreferenceFragment {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttach(Activity activity) {
|
|
||||||
super.onAttach(activity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle paramBundle) {
|
|
||||||
super.onCreate(paramBundle);
|
|
||||||
|
|
||||||
this.findPreference(TextSecurePreferences.SCREEN_LOCK).setOnPreferenceChangeListener(new ScreenLockListener());
|
|
||||||
|
|
||||||
this.findPreference(TextSecurePreferences.READ_RECEIPTS_PREF).setOnPreferenceChangeListener(new ReadReceiptToggleListener());
|
|
||||||
this.findPreference(TextSecurePreferences.TYPING_INDICATORS).setOnPreferenceChangeListener(new TypingIndicatorsToggleListener());
|
|
||||||
this.findPreference(TextSecurePreferences.LINK_PREVIEWS).setOnPreferenceChangeListener(new LinkPreviewToggleListener());
|
|
||||||
this.findPreference(TextSecurePreferences.CALL_NOTIFICATIONS_ENABLED).setOnPreferenceChangeListener(new CallToggleListener(this, this::setCall));
|
|
||||||
|
|
||||||
initializeVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Void setCall(boolean isEnabled) {
|
|
||||||
((SwitchPreferenceCompat)findPreference(TextSecurePreferences.CALL_NOTIFICATIONS_ENABLED)).setChecked(isEnabled);
|
|
||||||
if (isEnabled && !CallNotificationBuilder.areNotificationsEnabled(requireActivity())) {
|
|
||||||
// show a dialog saying that calls won't work properly if you don't have notifications on at a system level
|
|
||||||
new AlertDialog.Builder(new ContextThemeWrapper(requireActivity(), R.style.ThemeOverlay_Session_AlertDialog))
|
|
||||||
.setTitle(R.string.CallNotificationBuilder_system_notification_title)
|
|
||||||
.setMessage(R.string.CallNotificationBuilder_system_notification_message)
|
|
||||||
.setPositiveButton(R.string.activity_notification_settings_title, (d, w) -> {
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
|
||||||
Intent settingsIntent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID);
|
|
||||||
if (IntentUtils.isResolvable(requireContext(), settingsIntent)) {
|
|
||||||
startActivity(settingsIntent);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Intent settingsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
.setData(Uri.parse("package:"+BuildConfig.APPLICATION_ID));
|
|
||||||
if (IntentUtils.isResolvable(requireContext(), settingsIntent)) {
|
|
||||||
startActivity(settingsIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
d.dismiss();
|
|
||||||
})
|
|
||||||
.setNeutralButton(R.string.dismiss, (d, w) -> {
|
|
||||||
// do nothing, user might have broken notifications
|
|
||||||
d.dismiss();
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
||||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
|
|
||||||
addPreferencesFromResource(R.xml.preferences_app_protection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeVisibility() {
|
|
||||||
if (TextSecurePreferences.isPasswordDisabled(getContext())) {
|
|
||||||
KeyguardManager keyguardManager = (KeyguardManager)getContext().getSystemService(Context.KEYGUARD_SERVICE);
|
|
||||||
if (!keyguardManager.isKeyguardSecure()) {
|
|
||||||
((SwitchPreferenceCompat)findPreference(TextSecurePreferences.SCREEN_LOCK)).setChecked(false);
|
|
||||||
findPreference(TextSecurePreferences.SCREEN_LOCK).setEnabled(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
findPreference(TextSecurePreferences.SCREEN_LOCK).setVisible(false);
|
|
||||||
findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT).setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ScreenLockListener implements Preference.OnPreferenceChangeListener {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
boolean enabled = (Boolean)newValue;
|
|
||||||
|
|
||||||
TextSecurePreferences.setScreenLockEnabled(getContext(), enabled);
|
|
||||||
|
|
||||||
Intent intent = new Intent(getContext(), KeyCachingService.class);
|
|
||||||
intent.setAction(KeyCachingService.LOCK_TOGGLED_EVENT);
|
|
||||||
getContext().startService(intent);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ReadReceiptToggleListener implements Preference.OnPreferenceChangeListener {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TypingIndicatorsToggleListener implements Preference.OnPreferenceChangeListener {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
boolean enabled = (boolean)newValue;
|
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
ApplicationContext.getInstance(requireContext()).getTypingStatusRepository().clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LinkPreviewToggleListener implements Preference.OnPreferenceChangeListener {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CallToggleListener implements Preference.OnPreferenceChangeListener {
|
|
||||||
|
|
||||||
private final Fragment context;
|
|
||||||
private final Function1<Boolean, Void> setCallback;
|
|
||||||
|
|
||||||
private CallToggleListener(Fragment context, Function1<Boolean,Void> setCallback) {
|
|
||||||
this.context = context;
|
|
||||||
this.setCallback = setCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestMicrophonePermission() {
|
|
||||||
Permissions.with(context)
|
|
||||||
.request(Manifest.permission.RECORD_AUDIO)
|
|
||||||
.onAllGranted(() -> {
|
|
||||||
TextSecurePreferences.setBooleanPreference(context.requireContext(), TextSecurePreferences.CALL_NOTIFICATIONS_ENABLED, true);
|
|
||||||
setCallback.invoke(true);
|
|
||||||
})
|
|
||||||
.onAnyDenied(() -> setCallback.invoke(false))
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
boolean val = (boolean) newValue;
|
|
||||||
if (val) {
|
|
||||||
// check if we've shown the info dialog and check for microphone permissions
|
|
||||||
AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(context.requireContext(), R.style.ThemeOverlay_Session_AlertDialog))
|
|
||||||
.setTitle(R.string.dialog_voice_video_title)
|
|
||||||
.setMessage(R.string.dialog_voice_video_message)
|
|
||||||
.setPositiveButton(R.string.dialog_link_preview_enable_button_title, (d, w) -> {
|
|
||||||
requestMicrophonePermission();
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.cancel, (d, w) -> {
|
|
||||||
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
|
||||||
positiveButton.setContentDescription("Enable");
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,114 @@
|
|||||||
|
package org.thoughtcrime.securesms.preferences
|
||||||
|
|
||||||
|
import android.app.KeyguardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import network.loki.messenger.BuildConfig
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
|
import org.session.libsession.utilities.TextSecurePreferences.Companion.isPasswordDisabled
|
||||||
|
import org.session.libsession.utilities.TextSecurePreferences.Companion.setScreenLockEnabled
|
||||||
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
|
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||||
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
|
import org.thoughtcrime.securesms.service.KeyCachingService
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
|
import org.thoughtcrime.securesms.util.CallNotificationBuilder.Companion.areNotificationsEnabled
|
||||||
|
import org.thoughtcrime.securesms.util.IntentUtils
|
||||||
|
|
||||||
|
class PrivacySettingsPreferenceFragment : ListSummaryPreferenceFragment() {
|
||||||
|
override fun onCreate(paramBundle: Bundle?) {
|
||||||
|
super.onCreate(paramBundle)
|
||||||
|
findPreference<Preference>(TextSecurePreferences.SCREEN_LOCK)!!
|
||||||
|
.onPreferenceChangeListener = ScreenLockListener()
|
||||||
|
findPreference<Preference>(TextSecurePreferences.TYPING_INDICATORS)!!
|
||||||
|
.onPreferenceChangeListener = TypingIndicatorsToggleListener()
|
||||||
|
findPreference<Preference>(TextSecurePreferences.CALL_NOTIFICATIONS_ENABLED)!!
|
||||||
|
.onPreferenceChangeListener = CallToggleListener(this) { setCall(it) }
|
||||||
|
initializeVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setCall(isEnabled: Boolean) {
|
||||||
|
(findPreference<Preference>(TextSecurePreferences.CALL_NOTIFICATIONS_ENABLED) as SwitchPreferenceCompat?)!!.isChecked =
|
||||||
|
isEnabled
|
||||||
|
if (isEnabled && !areNotificationsEnabled(requireActivity())) {
|
||||||
|
// show a dialog saying that calls won't work properly if you don't have notifications on at a system level
|
||||||
|
showSessionDialog {
|
||||||
|
title(R.string.CallNotificationBuilder_system_notification_title)
|
||||||
|
text(R.string.CallNotificationBuilder_system_notification_message)
|
||||||
|
button(R.string.activity_notification_settings_title) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
||||||
|
.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID)
|
||||||
|
} else {
|
||||||
|
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||||
|
.setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID))
|
||||||
|
}
|
||||||
|
.apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
|
||||||
|
.takeIf { IntentUtils.isResolvable(requireContext(), it) }.let {
|
||||||
|
startActivity(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button(R.string.dismiss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(
|
||||||
|
requestCode: Int,
|
||||||
|
permissions: Array<String>,
|
||||||
|
grantResults: IntArray
|
||||||
|
) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
|
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
addPreferencesFromResource(R.xml.preferences_app_protection)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeVisibility() {
|
||||||
|
if (isPasswordDisabled(requireContext())) {
|
||||||
|
val keyguardManager =
|
||||||
|
requireContext().getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
||||||
|
if (!keyguardManager.isKeyguardSecure) {
|
||||||
|
findPreference<SwitchPreferenceCompat>(TextSecurePreferences.SCREEN_LOCK)!!.isChecked = false
|
||||||
|
findPreference<Preference>(TextSecurePreferences.SCREEN_LOCK)!!.isEnabled = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
findPreference<Preference>(TextSecurePreferences.SCREEN_LOCK)!!.isVisible = false
|
||||||
|
findPreference<Preference>(TextSecurePreferences.SCREEN_LOCK_TIMEOUT)!!.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class ScreenLockListener : Preference.OnPreferenceChangeListener {
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||||
|
val enabled = newValue as Boolean
|
||||||
|
setScreenLockEnabled(context!!, enabled)
|
||||||
|
val intent = Intent(context, KeyCachingService::class.java)
|
||||||
|
intent.action = KeyCachingService.LOCK_TOGGLED_EVENT
|
||||||
|
context!!.startService(intent)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class TypingIndicatorsToggleListener : Preference.OnPreferenceChangeListener {
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
|
||||||
|
val enabled = newValue as Boolean
|
||||||
|
if (!enabled) {
|
||||||
|
ApplicationContext.getInstance(requireContext()).typingStatusRepository.clear()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,38 +1,34 @@
|
|||||||
package org.thoughtcrime.securesms.preferences
|
package org.thoughtcrime.securesms.preferences
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.fragment.app.DialogFragment
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.DialogSeedBinding
|
|
||||||
import org.session.libsignal.crypto.MnemonicCodec
|
import org.session.libsignal.crypto.MnemonicCodec
|
||||||
import org.session.libsignal.utilities.hexEncodedPrivateKey
|
import org.session.libsignal.utilities.hexEncodedPrivateKey
|
||||||
|
import org.thoughtcrime.securesms.createSessionDialog
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||||
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
|
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
|
||||||
|
|
||||||
class SeedDialog : BaseDialog() {
|
|
||||||
|
|
||||||
|
class SeedDialog: DialogFragment() {
|
||||||
private val seed by lazy {
|
private val seed by lazy {
|
||||||
var hexEncodedSeed = IdentityKeyUtil.retrieve(requireContext(), IdentityKeyUtil.LOKI_SEED)
|
val hexEncodedSeed = IdentityKeyUtil.retrieve(requireContext(), IdentityKeyUtil.LOKI_SEED)
|
||||||
if (hexEncodedSeed == null) {
|
?: IdentityKeyUtil.getIdentityKeyPair(requireContext()).hexEncodedPrivateKey // Legacy account
|
||||||
hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(requireContext()).hexEncodedPrivateKey // Legacy account
|
|
||||||
}
|
MnemonicCodec { fileName -> MnemonicUtilities.loadFileContents(requireContext(), fileName) }
|
||||||
val loadFileContents: (String) -> String = { fileName ->
|
.encode(hexEncodedSeed, MnemonicCodec.Language.Configuration.english)
|
||||||
MnemonicUtilities.loadFileContents(requireContext(), fileName)
|
|
||||||
}
|
|
||||||
MnemonicCodec(loadFileContents).encode(hexEncodedSeed!!, MnemonicCodec.Language.Configuration.english)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setContentView(builder: AlertDialog.Builder) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
val binding = DialogSeedBinding.inflate(LayoutInflater.from(requireContext()))
|
title(R.string.dialog_seed_title)
|
||||||
binding.seedTextView.text = seed
|
text(R.string.dialog_seed_explanation)
|
||||||
binding.closeButton.setOnClickListener { dismiss() }
|
text(seed, R.style.SessionIDTextView)
|
||||||
binding.copyButton.setOnClickListener { copySeed() }
|
button(R.string.copy, R.string.AccessibilityId_copy_recovery_phrase) { copySeed() }
|
||||||
builder.setView(binding.root)
|
button(R.string.close) { dismiss() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copySeed() {
|
private fun copySeed() {
|
||||||
|
@ -16,7 +16,6 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import network.loki.messenger.BuildConfig
|
import network.loki.messenger.BuildConfig
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
@ -40,6 +39,7 @@ import org.thoughtcrime.securesms.mms.GlideRequests
|
|||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
import org.thoughtcrime.securesms.preferences.appearance.AppearanceSettingsActivity
|
import org.thoughtcrime.securesms.preferences.appearance.AppearanceSettingsActivity
|
||||||
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints
|
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
import org.thoughtcrime.securesms.util.BitmapDecodingException
|
import org.thoughtcrime.securesms.util.BitmapDecodingException
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil
|
import org.thoughtcrime.securesms.util.BitmapUtil
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
@ -264,19 +264,15 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showEditProfilePictureUI() {
|
private fun showEditProfilePictureUI() {
|
||||||
AlertDialog.Builder(this)
|
showSessionDialog {
|
||||||
.setTitle(R.string.activity_settings_set_display_picture)
|
title(R.string.activity_settings_set_display_picture)
|
||||||
.setView(R.layout.dialog_change_avatar)
|
view(R.layout.dialog_change_avatar)
|
||||||
.setPositiveButton(R.string.activity_settings_upload) { _, _ ->
|
button(R.string.activity_settings_upload) { startAvatarSelection() }
|
||||||
startAvatarSelection()
|
|
||||||
}
|
|
||||||
.setNegativeButton(R.string.cancel) { _, _ -> }
|
|
||||||
.apply {
|
|
||||||
if (TextSecurePreferences.getProfileAvatarId(context) != 0) {
|
if (TextSecurePreferences.getProfileAvatarId(context) != 0) {
|
||||||
setNeutralButton(R.string.activity_settings_remove) { _, _ -> removeAvatar() }
|
button(R.string.activity_settings_remove) { removeAvatar() }
|
||||||
}
|
}
|
||||||
}
|
cancelButton()
|
||||||
.show().apply {
|
}.apply {
|
||||||
val profilePic = findViewById<ProfilePictureView>(R.id.profile_picture_view)
|
val profilePic = findViewById<ProfilePictureView>(R.id.profile_picture_view)
|
||||||
?.also(::setupProfilePictureView)
|
?.also(::setupProfilePictureView)
|
||||||
|
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
package org.thoughtcrime.securesms.preferences
|
package org.thoughtcrime.securesms.preferences
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.media.MediaScannerConnection
|
import android.media.MediaScannerConnection
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
@ -20,11 +21,10 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import network.loki.messenger.BuildConfig
|
import network.loki.messenger.BuildConfig
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.DialogShareLogsBinding
|
|
||||||
import org.session.libsignal.utilities.ExternalStorageUtil
|
import org.session.libsignal.utilities.ExternalStorageUtil
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import org.thoughtcrime.securesms.createSessionDialog
|
||||||
import org.thoughtcrime.securesms.util.FileProviderUtil
|
import org.thoughtcrime.securesms.util.FileProviderUtil
|
||||||
import org.thoughtcrime.securesms.util.StreamUtil
|
import org.thoughtcrime.securesms.util.StreamUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -33,21 +33,15 @@ import java.io.IOException
|
|||||||
import java.util.Objects
|
import java.util.Objects
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class ShareLogsDialog : BaseDialog() {
|
class ShareLogsDialog : DialogFragment() {
|
||||||
|
|
||||||
private var shareJob: Job? = null
|
private var shareJob: Job? = null
|
||||||
|
|
||||||
override fun setContentView(builder: AlertDialog.Builder) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = createSessionDialog {
|
||||||
val binding = DialogShareLogsBinding.inflate(LayoutInflater.from(requireContext()))
|
title(R.string.dialog_share_logs_title)
|
||||||
binding.cancelButton.setOnClickListener {
|
text(R.string.dialog_share_logs_explanation)
|
||||||
dismiss()
|
button(R.string.share) { shareLogs() }
|
||||||
}
|
cancelButton { dismiss() }
|
||||||
binding.shareButton.setOnClickListener {
|
|
||||||
// start the export and share
|
|
||||||
shareLogs()
|
|
||||||
}
|
|
||||||
builder.setView(binding.root)
|
|
||||||
builder.setCancelable(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shareLogs() {
|
private fun shareLogs() {
|
||||||
|
@ -7,10 +7,10 @@ import android.view.View
|
|||||||
import androidx.annotation.StyleRes
|
import androidx.annotation.StyleRes
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
|
||||||
|
|
||||||
fun BaseActionBarActivity.setUpActionBarSessionLogo(hideBackButton: Boolean = false) {
|
fun BaseActionBarActivity.setUpActionBarSessionLogo(hideBackButton: Boolean = false) {
|
||||||
val actionbar = supportActionBar!!
|
val actionbar = supportActionBar!!
|
||||||
@ -66,7 +66,7 @@ interface ActivityDispatcher {
|
|||||||
fun get(context: Context) = context.getSystemService(SERVICE) as? ActivityDispatcher
|
fun get(context: Context) = context.getSystemService(SERVICE) as? ActivityDispatcher
|
||||||
}
|
}
|
||||||
fun dispatchIntent(body: (Context)->Intent?)
|
fun dispatchIntent(body: (Context)->Intent?)
|
||||||
fun showDialog(baseDialog: BaseDialog, tag: String? = null)
|
fun showDialog(dialogFragment: DialogFragment, tag: String? = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TextSecurePreferences.themeState(): ThemeState {
|
fun TextSecurePreferences.themeState(): ThemeState {
|
||||||
|
@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.util
|
|||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.DialogInterface.OnClickListener
|
|
||||||
import android.media.MediaScannerConnection
|
import android.media.MediaScannerConnection
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
@ -12,12 +11,12 @@ import android.provider.MediaStore
|
|||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.utilities.task.ProgressDialogAsyncTask
|
import org.session.libsession.utilities.task.ProgressDialogAsyncTask
|
||||||
import org.session.libsignal.utilities.ExternalStorageUtil
|
import org.session.libsignal.utilities.ExternalStorageUtil
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||||
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -30,7 +29,12 @@ import java.util.concurrent.TimeUnit
|
|||||||
* Saves attachment files to an external storage using [MediaStore] API.
|
* Saves attachment files to an external storage using [MediaStore] API.
|
||||||
* Requires [android.Manifest.permission.WRITE_EXTERNAL_STORAGE] on API 28 and below.
|
* Requires [android.Manifest.permission.WRITE_EXTERNAL_STORAGE] on API 28 and below.
|
||||||
*/
|
*/
|
||||||
class SaveAttachmentTask : ProgressDialogAsyncTask<SaveAttachmentTask.Attachment, Void, Pair<Int, String?>> {
|
class SaveAttachmentTask @JvmOverloads constructor(context: Context, count: Int = 1) :
|
||||||
|
ProgressDialogAsyncTask<SaveAttachmentTask.Attachment, Void, Pair<Int, String?>>(
|
||||||
|
context,
|
||||||
|
context.resources.getQuantityString(R.plurals.ConversationFragment_saving_n_attachments, count, count),
|
||||||
|
context.resources.getQuantityString(R.plurals.ConversationFragment_saving_n_attachments_to_sd_card, count, count)
|
||||||
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ -41,30 +45,25 @@ class SaveAttachmentTask : ProgressDialogAsyncTask<SaveAttachmentTask.Attachment
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun showWarningDialog(context: Context, onAcceptListener: OnClickListener, count: Int = 1) {
|
fun showWarningDialog(context: Context, count: Int = 1, onAcceptListener: () -> Unit = {}) {
|
||||||
val builder = AlertDialog.Builder(context)
|
context.showSessionDialog {
|
||||||
builder.setTitle(R.string.ConversationFragment_save_to_sd_card)
|
title(R.string.ConversationFragment_save_to_sd_card)
|
||||||
builder.setIconAttribute(R.attr.dialog_alert_icon)
|
iconAttribute(R.attr.dialog_alert_icon)
|
||||||
builder.setCancelable(true)
|
text(context.resources.getQuantityString(
|
||||||
builder.setMessage(context.resources.getQuantityString(
|
|
||||||
R.plurals.ConversationFragment_saving_n_media_to_storage_warning,
|
R.plurals.ConversationFragment_saving_n_media_to_storage_warning,
|
||||||
count,
|
count,
|
||||||
count))
|
count))
|
||||||
builder.setPositiveButton(R.string.yes, onAcceptListener)
|
button(R.string.yes) { onAcceptListener() }
|
||||||
builder.setNegativeButton(R.string.no, null)
|
button(R.string.no)
|
||||||
builder.show()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val contextReference: WeakReference<Context>
|
private val contextReference: WeakReference<Context>
|
||||||
private val attachmentCount: Int
|
private val attachmentCount: Int = count
|
||||||
|
|
||||||
@JvmOverloads
|
init {
|
||||||
constructor(context: Context, count: Int = 1): super(context,
|
|
||||||
context.resources.getQuantityString(R.plurals.ConversationFragment_saving_n_attachments, count, count),
|
|
||||||
context.resources.getQuantityString(R.plurals.ConversationFragment_saving_n_attachments_to_sd_card, count, count)) {
|
|
||||||
this.contextReference = WeakReference(context)
|
this.contextReference = WeakReference(context)
|
||||||
this.attachmentCount = count
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doInBackground(vararg attachments: Attachment?): Pair<Int, String?> {
|
override fun doInBackground(vararg attachments: Attachment?): Pair<Int, String?> {
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:elevation="4dp"
|
|
||||||
android:padding="@dimen/medium_spacing">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/blockedTitleTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_blocked_title"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/large_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/blockedExplanationTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="@string/dialog_blocked_explanation"
|
|
||||||
android:paddingHorizontal="@dimen/medium_spacing"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/small_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/cancelButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/cancel" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/unblockButton"
|
|
||||||
android:contentDescription="@string/AccessibilityId_block_confirm"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="@dimen/medium_spacing"
|
|
||||||
android:text="@string/ConversationActivity_unblock" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,58 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:elevation="4dp"
|
|
||||||
android:padding="@dimen/medium_spacing">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/downloadTitleTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_download_title"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/large_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/downloadExplanationTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="@string/dialog_download_explanation"
|
|
||||||
android:paddingHorizontal="@dimen/medium_spacing"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/small_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/cancelButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:contentDescription="@string/AccessibilityId_dont_download_media"
|
|
||||||
android:text="@string/cancel" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/downloadButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="@dimen/medium_spacing"
|
|
||||||
android:contentDescription="@string/AccessibilityId_download_media"
|
|
||||||
android:text="@string/dialog_download_button_title" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,56 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:elevation="4dp"
|
|
||||||
android:padding="@dimen/medium_spacing">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/joinOpenGroupTitleTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_join_open_group_title"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/large_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/joinOpenGroupExplanationTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="@string/dialog_join_open_group_explanation"
|
|
||||||
android:paddingHorizontal="@dimen/medium_spacing"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/small_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/cancelButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/cancel" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/joinButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="@dimen/medium_spacing"
|
|
||||||
android:text="@string/open_group_invitation_view__join_accessibility_description" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,60 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:elevation="4dp"
|
|
||||||
android:padding="@dimen/medium_spacing">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/linkPreviewDialogTitleTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_link_preview_title"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/large_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/linkPreviewDialogExplanationTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="@string/dialog_link_preview_explanation"
|
|
||||||
android:paddingHorizontal="@dimen/medium_spacing"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/small_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/cancelButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/cancel"
|
|
||||||
android:contentDescription="@string/AccessibilityId_cancel_link_preview_button"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/enableLinkPreviewsButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="@dimen/medium_spacing"
|
|
||||||
android:text="@string/dialog_link_preview_enable_button_title"
|
|
||||||
android:contentDescription="@string/AccessibilityId_enable_link_preview_button"
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,56 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:elevation="4dp"
|
|
||||||
android:padding="@dimen/medium_spacing">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/openURLTitleTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_open_url_title"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/large_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/openURLExplanationTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="@string/dialog_open_url_explanation"
|
|
||||||
android:paddingHorizontal="@dimen/medium_spacing"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/small_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/cancelButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/cancel" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/openURLButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="@dimen/medium_spacing"
|
|
||||||
android:text="@string/open" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,69 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="@dimen/medium_spacing">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_seed_title"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textSize="@dimen/medium_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="@string/dialog_seed_explanation"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/medium_font_size"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:alpha="0.6" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/SessionIDTextView"
|
|
||||||
android:contentDescription="@string/AccessibilityId_recovery_phrase"
|
|
||||||
android:id="@+id/seedTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:padding="@dimen/small_spacing"
|
|
||||||
tools:text="habitat kiwi amply iceberg dog nerves spiderman soft match partial awakened maximum degrees"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/small_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:contentDescription="@string/AccessibilityId_cancel_button"
|
|
||||||
android:id="@+id/copyButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="@dimen/medium_spacing"
|
|
||||||
android:text="@string/copy" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:contentDescription="@string/AccessibilityId_copy_recovery_phrase"
|
|
||||||
android:id="@+id/closeButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/close" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,63 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:elevation="4dp"
|
|
||||||
android:padding="@dimen/medium_spacing">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_share_logs_title"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="@dimen/medium_font_size" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dialogDescriptionText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:text="@string/dialog_share_logs_explanation"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/small_font_size"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/large_spacing"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/cancelButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/cancel" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Session.Button.Dialog.UnimportantText"
|
|
||||||
android:id="@+id/shareButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="@dimen/medium_spacing"
|
|
||||||
android:text="@string/share" />
|
|
||||||
|
|
||||||
<com.github.ybq.android.spinkit.SpinKitView
|
|
||||||
style="@style/SpinKitView.Small.ThreeBounce"
|
|
||||||
android:id="@+id/progressBar"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/small_button_height"
|
|
||||||
android:layout_weight="1"
|
|
||||||
app:SpinKit_Color="?colorAccent"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -169,14 +169,6 @@
|
|||||||
<item>@string/arrays__use_custom</item>
|
<item>@string/arrays__use_custom</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="mute_durations">
|
|
||||||
<item>@string/arrays__mute_for_one_hour</item>
|
|
||||||
<item>@string/arrays__mute_for_two_hours</item>
|
|
||||||
<item>@string/arrays__mute_for_one_day</item>
|
|
||||||
<item>@string/arrays__mute_for_seven_days</item>
|
|
||||||
<item>@string/arrays__mute_forever</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="pref_notification_privacy_entries">
|
<string-array name="pref_notification_privacy_entries">
|
||||||
<item>@string/arrays__name_and_message</item>
|
<item>@string/arrays__name_and_message</item>
|
||||||
<item>@string/arrays__name_only</item>
|
<item>@string/arrays__name_only</item>
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
|
|
||||||
<!-- TODO These button styles require proper background selectors for up/down visual state. -->
|
<!-- TODO These button styles require proper background selectors for up/down visual state. -->
|
||||||
<style name="Widget.Session.Button.Common" parent="">
|
<style name="Widget.Session.Button.Common" parent="">
|
||||||
|
<item name="android:gravity">center</item>
|
||||||
<item name="android:textAllCaps">false</item>
|
<item name="android:textAllCaps">false</item>
|
||||||
<item name="android:textSize">@dimen/medium_font_size</item>
|
<item name="android:textSize">@dimen/medium_font_size</item>
|
||||||
<item name="android:fontFamily">sans-serif-medium</item>
|
<item name="android:fontFamily">sans-serif-medium</item>
|
||||||
@ -110,6 +111,7 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Widget.Session.Button.Dialog" parent="">
|
<style name="Widget.Session.Button.Dialog" parent="">
|
||||||
|
<item name="android:gravity">center</item>
|
||||||
<item name="android:textAllCaps">false</item>
|
<item name="android:textAllCaps">false</item>
|
||||||
<item name="android:textSize">@dimen/small_font_size</item>
|
<item name="android:textSize">@dimen/small_font_size</item>
|
||||||
<item name="android:textColor">?android:textColorPrimary</item>
|
<item name="android:textColor">?android:textColorPrimary</item>
|
||||||
|
Loading…
Reference in New Issue
Block a user