kopia lustrzana https://github.com/ryukoposting/Signal-Android
Always ensure the send type matches the send button.
rodzic
852989ce48
commit
4c4cfe917d
|
@ -832,7 +832,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
||||||
int subscriptionId = sendButton.getSelectedSendType().getSimSubscriptionIdOr(-1);
|
|
||||||
boolean initiating = threadId == -1;
|
boolean initiating = threadId == -1;
|
||||||
QuoteModel quote = result.isViewOnce() ? null : inputPanel.getQuote().orElse(null);
|
QuoteModel quote = result.isViewOnce() ? null : inputPanel.getQuote().orElse(null);
|
||||||
SlideDeck slideDeck = new SlideDeck();
|
SlideDeck slideDeck = new SlideDeck();
|
||||||
|
@ -853,7 +852,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
final Context context = requireContext().getApplicationContext();
|
final Context context = requireContext().getApplicationContext();
|
||||||
|
|
||||||
sendMediaMessage(result.getRecipientId(),
|
sendMediaMessage(result.getRecipientId(),
|
||||||
result.getMessageSendType().usesSmsTransport(),
|
result.getMessageSendType(),
|
||||||
result.getBody(),
|
result.getBody(),
|
||||||
slideDeck,
|
slideDeck,
|
||||||
quote,
|
quote,
|
||||||
|
@ -862,7 +861,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
mentions,
|
mentions,
|
||||||
expiresIn,
|
expiresIn,
|
||||||
result.isViewOnce(),
|
result.isViewOnce(),
|
||||||
subscriptionId,
|
|
||||||
initiating,
|
initiating,
|
||||||
true,
|
true,
|
||||||
null).addListener(new AssertedSuccessListener<Void>() {
|
null).addListener(new AssertedSuccessListener<Void>() {
|
||||||
|
@ -2758,11 +2756,10 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendSharedContact(List<Contact> contacts) {
|
private void sendSharedContact(List<Contact> contacts) {
|
||||||
int subscriptionId = sendButton.getSelectedSendType().getSimSubscriptionIdOr(-1);
|
|
||||||
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
||||||
boolean initiating = threadId == -1;
|
boolean initiating = threadId == -1;
|
||||||
|
|
||||||
sendMediaMessage(recipient.getId(), isSmsForced(), "", attachmentManager.buildSlideDeck(), null, contacts, Collections.emptyList(), Collections.emptyList(), expiresIn, false, subscriptionId, initiating, false, null);
|
sendMediaMessage(recipient.getId(), sendButton.getSelectedSendType(), "", attachmentManager.buildSlideDeck(), null, contacts, Collections.emptyList(), Collections.emptyList(), expiresIn, false, initiating, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void selectContactInfo(ContactData contactData) {
|
private void selectContactInfo(ContactData contactData) {
|
||||||
|
@ -3060,8 +3057,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
|
|
||||||
String message = getMessage();
|
String message = getMessage();
|
||||||
MessageSendType sendType = sendButton.getSelectedSendType();
|
MessageSendType sendType = sendButton.getSelectedSendType();
|
||||||
boolean forceSms = (recipient.isForceSmsSelection() || sendButton.isManualSelection()) && sendType.usesSmsTransport();
|
|
||||||
int subscriptionId = sendButton.getSelectedSendType().getSimSubscriptionIdOr(-1);
|
|
||||||
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.getExpiresInSeconds());
|
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.getExpiresInSeconds());
|
||||||
boolean initiating = threadId == -1;
|
boolean initiating = threadId == -1;
|
||||||
boolean needsSplit = !sendType.usesSmsTransport() && message.length() > sendType.calculateCharacters(message).maxPrimaryMessageSize;
|
boolean needsSplit = !sendType.usesSmsTransport() && message.length() > sendType.calculateCharacters(message).maxPrimaryMessageSize;
|
||||||
|
@ -3073,16 +3068,16 @@ public class ConversationParentFragment extends Fragment
|
||||||
linkPreviewViewModel.hasLinkPreview() ||
|
linkPreviewViewModel.hasLinkPreview() ||
|
||||||
needsSplit;
|
needsSplit;
|
||||||
|
|
||||||
Log.i(TAG, "[sendMessage] recipient: " + recipient.getId() + ", threadId: " + threadId + ", forceSms: " + forceSms + ", isManual: " + sendButton.isManualSelection());
|
Log.i(TAG, "[sendMessage] recipient: " + recipient.getId() + ", threadId: " + threadId + ", sendType: " + (sendType.usesSignalTransport() ? "signal" : "sms") + ", isManual: " + sendButton.isManualSelection());
|
||||||
|
|
||||||
if ((recipient.isMmsGroup() || recipient.getEmail().isPresent()) && !isMmsEnabled) {
|
if ((recipient.isMmsGroup() || recipient.getEmail().isPresent()) && !isMmsEnabled) {
|
||||||
handleManualMmsRequired();
|
handleManualMmsRequired();
|
||||||
} else if (!forceSms && (identityRecords.isUnverified(true) || identityRecords.isUntrusted(true))) {
|
} else if (sendType.usesSignalTransport() && (identityRecords.isUnverified(true) || identityRecords.isUntrusted(true))) {
|
||||||
handleRecentSafetyNumberChange();
|
handleRecentSafetyNumberChange();
|
||||||
} else if (isMediaMessage) {
|
} else if (isMediaMessage) {
|
||||||
sendMediaMessage(forceSms, expiresIn, false, subscriptionId, initiating, metricId);
|
sendMediaMessage(sendType, expiresIn, false, initiating, metricId);
|
||||||
} else {
|
} else {
|
||||||
sendTextMessage(forceSms, expiresIn, subscriptionId, initiating, metricId);
|
sendTextMessage(sendType, expiresIn, initiating, metricId);
|
||||||
}
|
}
|
||||||
} catch (RecipientFormattingException ex) {
|
} catch (RecipientFormattingException ex) {
|
||||||
Toast.makeText(requireContext(),
|
Toast.makeText(requireContext(),
|
||||||
|
@ -3124,13 +3119,13 @@ public class ConversationParentFragment extends Fragment
|
||||||
}, this::sendComplete);
|
}, this::sendComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMediaMessage(final boolean forceSms, final long expiresIn, final boolean viewOnce, final int subscriptionId, final boolean initiating, @Nullable String metricId)
|
private void sendMediaMessage(@NonNull MessageSendType sendType, final long expiresIn, final boolean viewOnce, final boolean initiating, @Nullable String metricId)
|
||||||
throws InvalidMessageException
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
Log.i(TAG, "Sending media message...");
|
Log.i(TAG, "Sending media message...");
|
||||||
List<LinkPreview> linkPreviews = linkPreviewViewModel.onSend();
|
List<LinkPreview> linkPreviews = linkPreviewViewModel.onSend();
|
||||||
sendMediaMessage(recipient.getId(),
|
sendMediaMessage(recipient.getId(),
|
||||||
forceSms,
|
sendType,
|
||||||
getMessage(),
|
getMessage(),
|
||||||
attachmentManager.buildSlideDeck(),
|
attachmentManager.buildSlideDeck(),
|
||||||
inputPanel.getQuote().orElse(null),
|
inputPanel.getQuote().orElse(null),
|
||||||
|
@ -3139,14 +3134,13 @@ public class ConversationParentFragment extends Fragment
|
||||||
composeText.getMentions(),
|
composeText.getMentions(),
|
||||||
expiresIn,
|
expiresIn,
|
||||||
viewOnce,
|
viewOnce,
|
||||||
subscriptionId,
|
|
||||||
initiating,
|
initiating,
|
||||||
true,
|
true,
|
||||||
metricId);
|
metricId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListenableFuture<Void> sendMediaMessage(@NonNull RecipientId recipientId,
|
private ListenableFuture<Void> sendMediaMessage(@NonNull RecipientId recipientId,
|
||||||
final boolean forceSms,
|
@NonNull MessageSendType sendType,
|
||||||
@NonNull String body,
|
@NonNull String body,
|
||||||
SlideDeck slideDeck,
|
SlideDeck slideDeck,
|
||||||
QuoteModel quote,
|
QuoteModel quote,
|
||||||
|
@ -3155,17 +3149,16 @@ public class ConversationParentFragment extends Fragment
|
||||||
List<Mention> mentions,
|
List<Mention> mentions,
|
||||||
final long expiresIn,
|
final long expiresIn,
|
||||||
final boolean viewOnce,
|
final boolean viewOnce,
|
||||||
final int subscriptionId,
|
|
||||||
final boolean initiating,
|
final boolean initiating,
|
||||||
final boolean clearComposeBox,
|
final boolean clearComposeBox,
|
||||||
final @Nullable String metricId)
|
final @Nullable String metricId)
|
||||||
{
|
{
|
||||||
if (!isDefaultSms && (!isSecureText || forceSms) && recipient.get().hasSmsAddress()) {
|
if (!isDefaultSms && sendType.usesSmsTransport() && recipient.get().hasSmsAddress()) {
|
||||||
showDefaultSmsPrompt();
|
showDefaultSmsPrompt();
|
||||||
return new SettableFuture<>(null);
|
return new SettableFuture<>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isServiceIdOnly();
|
final boolean sendPush = sendType.usesSignalTransport();
|
||||||
final long thread = this.threadId;
|
final long thread = this.threadId;
|
||||||
|
|
||||||
if (sendPush) {
|
if (sendPush) {
|
||||||
|
@ -3177,7 +3170,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OutgoingMediaMessage outgoingMessageCandidate = new OutgoingMediaMessage(Recipient.resolved(recipientId), slideDeck, body, System.currentTimeMillis(), subscriptionId, expiresIn, viewOnce, distributionType, StoryType.NONE, null, false, quote, contacts, previews, mentions, null);
|
OutgoingMediaMessage outgoingMessageCandidate = new OutgoingMediaMessage(Recipient.resolved(recipientId), slideDeck, body, System.currentTimeMillis(), sendType.getSimSubscriptionIdOr(-1), expiresIn, viewOnce, distributionType, StoryType.NONE, null, false, quote, contacts, previews, mentions, null);
|
||||||
|
|
||||||
final SettableFuture<Void> future = new SettableFuture<>();
|
final SettableFuture<Void> future = new SettableFuture<>();
|
||||||
final Context context = requireContext().getApplicationContext();
|
final Context context = requireContext().getApplicationContext();
|
||||||
|
@ -3205,7 +3198,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
final long id = fragment.stageOutgoingMessage(outgoingMessage);
|
final long id = fragment.stageOutgoingMessage(outgoingMessage);
|
||||||
|
|
||||||
SimpleTask.run(() -> {
|
SimpleTask.run(() -> {
|
||||||
return MessageSender.send(context, outgoingMessage, thread, forceSms, metricId, null);
|
return MessageSender.send(context, outgoingMessage, thread, sendType.usesSmsTransport(), metricId, null);
|
||||||
}, result -> {
|
}, result -> {
|
||||||
sendComplete(result);
|
sendComplete(result);
|
||||||
future.set(null);
|
future.set(null);
|
||||||
|
@ -3217,10 +3210,10 @@ public class ConversationParentFragment extends Fragment
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendTextMessage(final boolean forceSms, final long expiresIn, final int subscriptionId, final boolean initiating, final @Nullable String metricId)
|
private void sendTextMessage(@NonNull MessageSendType sendType, final long expiresIn, final boolean initiating, final @Nullable String metricId)
|
||||||
throws InvalidMessageException
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
if (!isDefaultSms && (!isSecureText || forceSms) && recipient.get().hasSmsAddress()) {
|
if (!isDefaultSms && sendType.usesSmsTransport() && recipient.get().hasSmsAddress()) {
|
||||||
showDefaultSmsPrompt();
|
showDefaultSmsPrompt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3228,7 +3221,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
final long thread = this.threadId;
|
final long thread = this.threadId;
|
||||||
final Context context = requireContext().getApplicationContext();
|
final Context context = requireContext().getApplicationContext();
|
||||||
final String messageBody = getMessage();
|
final String messageBody = getMessage();
|
||||||
final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isServiceIdOnly();
|
final boolean sendPush = sendType.usesSignalTransport();
|
||||||
|
|
||||||
OutgoingTextMessage message;
|
OutgoingTextMessage message;
|
||||||
|
|
||||||
|
@ -3236,7 +3229,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
message = new OutgoingEncryptedMessage(recipient.get(), messageBody, expiresIn);
|
message = new OutgoingEncryptedMessage(recipient.get(), messageBody, expiresIn);
|
||||||
ApplicationDependencies.getTypingStatusSender().onTypingStopped(thread);
|
ApplicationDependencies.getTypingStatusSender().onTypingStopped(thread);
|
||||||
} else {
|
} else {
|
||||||
message = new OutgoingTextMessage(recipient.get(), messageBody, expiresIn, subscriptionId);
|
message = new OutgoingTextMessage(recipient.get(), messageBody, expiresIn, sendType.getSimSubscriptionIdOr(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
Permissions.with(this)
|
Permissions.with(this)
|
||||||
|
@ -3246,7 +3239,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
.onAllGranted(() -> {
|
.onAllGranted(() -> {
|
||||||
final long id = new SecureRandom().nextLong();
|
final long id = new SecureRandom().nextLong();
|
||||||
SimpleTask.run(() -> {
|
SimpleTask.run(() -> {
|
||||||
return MessageSender.send(context, message, thread, forceSms, metricId, null);
|
return MessageSender.send(context, message, thread, sendType.usesSmsTransport(), metricId, null);
|
||||||
}, this::sendComplete);
|
}, this::sendComplete);
|
||||||
|
|
||||||
silentlySetComposeText("");
|
silentlySetComposeText("");
|
||||||
|
@ -3455,16 +3448,14 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendVoiceNote(@NonNull Uri uri, long size) {
|
private void sendVoiceNote(@NonNull Uri uri, long size) {
|
||||||
boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedSendType().usesSmsTransport();
|
|
||||||
boolean initiating = threadId == -1;
|
boolean initiating = threadId == -1;
|
||||||
int subscriptionId = sendButton.getSelectedSendType().getSimSubscriptionIdOr(-1);
|
|
||||||
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
||||||
AudioSlide audioSlide = new AudioSlide(requireContext(), uri, size, MediaUtil.AUDIO_AAC, true);
|
AudioSlide audioSlide = new AudioSlide(requireContext(), uri, size, MediaUtil.AUDIO_AAC, true);
|
||||||
SlideDeck slideDeck = new SlideDeck();
|
SlideDeck slideDeck = new SlideDeck();
|
||||||
slideDeck.addSlide(audioSlide);
|
slideDeck.addSlide(audioSlide);
|
||||||
|
|
||||||
ListenableFuture<Void> sendResult = sendMediaMessage(recipient.getId(),
|
ListenableFuture<Void> sendResult = sendMediaMessage(recipient.getId(),
|
||||||
forceSms,
|
sendButton.getSelectedSendType(),
|
||||||
"",
|
"",
|
||||||
slideDeck,
|
slideDeck,
|
||||||
inputPanel.getQuote().orElse(null),
|
inputPanel.getQuote().orElse(null),
|
||||||
|
@ -3473,7 +3464,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
composeText.getMentions(),
|
composeText.getMentions(),
|
||||||
expiresIn,
|
expiresIn,
|
||||||
false,
|
false,
|
||||||
subscriptionId,
|
|
||||||
initiating,
|
initiating,
|
||||||
true,
|
true,
|
||||||
null);
|
null);
|
||||||
|
@ -3504,7 +3494,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
||||||
int subscriptionId = sendButton.getSelectedSendType().getSimSubscriptionIdOr(-1);
|
|
||||||
boolean initiating = threadId == -1;
|
boolean initiating = threadId == -1;
|
||||||
MessageSendType sendType = sendButton.getSelectedSendType();
|
MessageSendType sendType = sendButton.getSelectedSendType();
|
||||||
SlideDeck slideDeck = new SlideDeck();
|
SlideDeck slideDeck = new SlideDeck();
|
||||||
|
@ -3512,7 +3501,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
|
|
||||||
slideDeck.addSlide(stickerSlide);
|
slideDeck.addSlide(stickerSlide);
|
||||||
|
|
||||||
sendMediaMessage(recipient.getId(), sendType.usesSmsTransport(), "", slideDeck, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), expiresIn, false, subscriptionId, initiating, clearCompose, null);
|
sendMediaMessage(recipient.getId(), sendType, "", slideDeck, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), expiresIn, false, initiating, clearCompose, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void silentlySetComposeText(String text) {
|
private void silentlySetComposeText(String text) {
|
||||||
|
@ -4155,7 +4144,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
|
||||||
int subscriptionId = sendButton.getSelectedSendType().getSimSubscriptionIdOr(-1);
|
|
||||||
boolean initiating = threadId == -1;
|
boolean initiating = threadId == -1;
|
||||||
SlideDeck slideDeck = new SlideDeck();
|
SlideDeck slideDeck = new SlideDeck();
|
||||||
|
|
||||||
|
@ -4168,7 +4156,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMediaMessage(recipient.getId(),
|
sendMediaMessage(recipient.getId(),
|
||||||
isSmsForced(),
|
sendButton.getSelectedSendType(),
|
||||||
"",
|
"",
|
||||||
slideDeck,
|
slideDeck,
|
||||||
null,
|
null,
|
||||||
|
@ -4177,7 +4165,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
composeText.getMentions(),
|
composeText.getMentions(),
|
||||||
expiresIn,
|
expiresIn,
|
||||||
false,
|
false,
|
||||||
subscriptionId,
|
|
||||||
initiating,
|
initiating,
|
||||||
false,
|
false,
|
||||||
null);
|
null);
|
||||||
|
|
|
@ -7,8 +7,8 @@ import androidx.annotation.ColorRes
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import org.signal.core.util.logging.Log
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
|
||||||
import org.thoughtcrime.securesms.util.CharacterCalculator
|
import org.thoughtcrime.securesms.util.CharacterCalculator
|
||||||
import org.thoughtcrime.securesms.util.MmsCharacterCalculator
|
import org.thoughtcrime.securesms.util.MmsCharacterCalculator
|
||||||
import org.thoughtcrime.securesms.util.PushCharacterCalculator
|
import org.thoughtcrime.securesms.util.PushCharacterCalculator
|
||||||
|
@ -125,6 +125,9 @@ sealed class MessageSendType(
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
private val TAG = Log.tag(MessageSendType::class.java)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all available [MessageSendType]s. Requires [Manifest.permission.READ_PHONE_STATE] in order to get available
|
* Returns a list of all available [MessageSendType]s. Requires [Manifest.permission.READ_PHONE_STATE] in order to get available
|
||||||
* SMS options.
|
* SMS options.
|
||||||
|
@ -135,22 +138,22 @@ sealed class MessageSendType(
|
||||||
|
|
||||||
options += SignalMessageSendType
|
options += SignalMessageSendType
|
||||||
|
|
||||||
if (!Permissions.hasAll(context, Manifest.permission.READ_PHONE_STATE)) {
|
try {
|
||||||
return options
|
val subscriptions: Collection<SubscriptionInfoCompat> = SubscriptionManagerCompat(context).activeAndReadySubscriptionInfos
|
||||||
}
|
|
||||||
|
|
||||||
val subscriptions: Collection<SubscriptionInfoCompat> = SubscriptionManagerCompat(context).activeAndReadySubscriptionInfos
|
if (subscriptions.size < 2) {
|
||||||
|
options += if (isMedia) MmsMessageSendType() else SmsMessageSendType()
|
||||||
if (subscriptions.size < 2) {
|
} else {
|
||||||
options += if (isMedia) MmsMessageSendType() else SmsMessageSendType()
|
options += subscriptions.map {
|
||||||
} else {
|
if (isMedia) {
|
||||||
options += subscriptions.map {
|
MmsMessageSendType(simName = it.displayName, simSubscriptionId = it.subscriptionId)
|
||||||
if (isMedia) {
|
} else {
|
||||||
MmsMessageSendType(simName = it.displayName, simSubscriptionId = it.subscriptionId)
|
SmsMessageSendType(simName = it.displayName, simSubscriptionId = it.subscriptionId)
|
||||||
} else {
|
}
|
||||||
SmsMessageSendType(simName = it.displayName, simSubscriptionId = it.subscriptionId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e: SecurityException) {
|
||||||
|
Log.w(TAG, "Did not have permission to get SMS subscription details!")
|
||||||
}
|
}
|
||||||
|
|
||||||
return options
|
return options
|
||||||
|
|
Ładowanie…
Reference in New Issue