Update link preview settings and add some UI polish.
This commit is contained in:
parent
676356e800
commit
ace1b8ee71
20 changed files with 336 additions and 37 deletions
|
@ -236,6 +236,11 @@ public class InputPanel extends LinearLayout
|
|||
this.linkPreview.setLoading();
|
||||
}
|
||||
|
||||
public void setLinkPreviewNoPreview() {
|
||||
this.linkPreview.setVisibility(View.VISIBLE);
|
||||
this.linkPreview.setNoPreview();
|
||||
}
|
||||
|
||||
public void setLinkPreview(@NonNull GlideRequests glideRequests, @NonNull Optional<LinkPreview> preview) {
|
||||
if (preview.isPresent()) {
|
||||
this.linkPreview.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -21,6 +21,9 @@ import org.thoughtcrime.securesms.util.ThemeUtil;
|
|||
|
||||
import okhttp3.HttpUrl;
|
||||
|
||||
/**
|
||||
* The view shown in the compose box that represents the state of the link preview.
|
||||
*/
|
||||
public class LinkPreviewView extends FrameLayout {
|
||||
|
||||
private static final int TYPE_CONVERSATION = 0;
|
||||
|
@ -33,6 +36,7 @@ public class LinkPreviewView extends FrameLayout {
|
|||
private View divider;
|
||||
private View closeButton;
|
||||
private View spinner;
|
||||
private View noPreview;
|
||||
|
||||
private int type;
|
||||
private int defaultRadius;
|
||||
|
@ -60,6 +64,7 @@ public class LinkPreviewView extends FrameLayout {
|
|||
divider = findViewById(R.id.linkpreview_divider);
|
||||
spinner = findViewById(R.id.linkpreview_progress_wheel);
|
||||
closeButton = findViewById(R.id.linkpreview_close);
|
||||
noPreview = findViewById(R.id.linkpreview_no_preview);
|
||||
defaultRadius = getResources().getDimensionPixelSize(R.dimen.thumbnail_default_radius);
|
||||
cornerMask = new CornerMask(this);
|
||||
outliner = new Outliner();
|
||||
|
@ -102,6 +107,15 @@ public class LinkPreviewView extends FrameLayout {
|
|||
site.setVisibility(GONE);
|
||||
thumbnail.setVisibility(GONE);
|
||||
spinner.setVisibility(VISIBLE);
|
||||
noPreview.setVisibility(INVISIBLE);
|
||||
}
|
||||
|
||||
public void setNoPreview() {
|
||||
title.setVisibility(GONE);
|
||||
site.setVisibility(GONE);
|
||||
thumbnail.setVisibility(GONE);
|
||||
spinner.setVisibility(GONE);
|
||||
noPreview.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
public void setLinkPreview(@NonNull GlideRequests glideRequests, @NonNull LinkPreview linkPreview, boolean showThumbnail) {
|
||||
|
@ -109,6 +123,7 @@ public class LinkPreviewView extends FrameLayout {
|
|||
site.setVisibility(VISIBLE);
|
||||
thumbnail.setVisibility(VISIBLE);
|
||||
spinner.setVisibility(GONE);
|
||||
noPreview.setVisibility(GONE);
|
||||
|
||||
title.setText(linkPreview.getTitle());
|
||||
|
||||
|
|
|
@ -1820,7 +1820,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
private void initializeLinkPreviewObserver() {
|
||||
linkPreviewViewModel = ViewModelProviders.of(this, new LinkPreviewViewModel.Factory(new LinkPreviewRepository())).get(LinkPreviewViewModel.class);
|
||||
|
||||
if (!TextSecurePreferences.isLinkPreviewsEnabled(this)) {
|
||||
if (!SignalStore.settings().isLinkPreviewsEnabled()) {
|
||||
linkPreviewViewModel.onUserCancel();
|
||||
return;
|
||||
}
|
||||
|
@ -1831,6 +1831,9 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
if (previewState.isLoading()) {
|
||||
Log.d(TAG, "Loading link preview.");
|
||||
inputPanel.setLinkPreviewLoading();
|
||||
} else if (previewState.hasLinks() && !previewState.getLinkPreview().isPresent()) {
|
||||
Log.d(TAG, "No preview found.");
|
||||
inputPanel.setLinkPreviewNoPreview();
|
||||
} else {
|
||||
Log.d(TAG, "Setting link preview: " + previewState.getLinkPreview().isPresent());
|
||||
inputPanel.setLinkPreview(glideRequests, previewState.getLinkPreview());
|
||||
|
@ -2591,7 +2594,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
buttonToggle.display(sendButton);
|
||||
quickAttachmentToggle.hide();
|
||||
|
||||
if (!attachmentManager.isAttachmentPresent() && !linkPreviewViewModel.hasLinkPreview()) {
|
||||
if (!attachmentManager.isAttachmentPresent() && !linkPreviewViewModel.hasLinkPreviewUi()) {
|
||||
inlineAttachmentToggle.show();
|
||||
} else {
|
||||
inlineAttachmentToggle.hide();
|
||||
|
@ -2600,7 +2603,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
}
|
||||
|
||||
private void updateLinkPreviewState() {
|
||||
if (TextSecurePreferences.isLinkPreviewsEnabled(this) && !sendButton.getSelectedTransport().isSms() && !attachmentManager.isAttachmentPresent()) {
|
||||
if (SignalStore.settings().isLinkPreviewsEnabled() && !sendButton.getSelectedTransport().isSms() && !attachmentManager.isAttachmentPresent()) {
|
||||
linkPreviewViewModel.onEnabled();
|
||||
linkPreviewViewModel.onTextChanged(this, composeText.getTextTrimmed().toString(), composeText.getSelectionStart(), composeText.getSelectionEnd());
|
||||
} else {
|
||||
|
|
|
@ -58,6 +58,7 @@ import org.thoughtcrime.securesms.jobmanager.Data;
|
|||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.linkpreview.Link;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||
|
@ -830,7 +831,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||
}
|
||||
|
||||
if (configurationMessage.getLinkPreviews().isPresent()) {
|
||||
TextSecurePreferences.setLinkPreviewsEnabled(context, configurationMessage.getReadReceipts().get());
|
||||
SignalStore.settings().setLinkPreviewsEnabled(configurationMessage.getReadReceipts().get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -966,7 +967,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||
ApplicationDependencies.getJobManager().add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(context),
|
||||
TextSecurePreferences.isTypingIndicatorsEnabled(context),
|
||||
TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(context),
|
||||
TextSecurePreferences.isLinkPreviewsEnabled(context)));
|
||||
SignalStore.settings().isLinkPreviewsEnabled()));
|
||||
ApplicationDependencies.getJobManager().add(new MultiDeviceStickerPackSyncJob());
|
||||
}
|
||||
|
||||
|
@ -1692,7 +1693,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||
Optional<String> url = Optional.fromNullable(preview.getUrl());
|
||||
Optional<String> title = Optional.fromNullable(preview.getTitle());
|
||||
boolean hasContent = !TextUtils.isEmpty(title.or("")) || thumbnail.isPresent();
|
||||
boolean presentInBody = url.isPresent() && Stream.of(LinkPreviewUtil.findWhitelistedUrls(message)).map(Link::getUrl).collect(Collectors.toSet()).contains(url.get());
|
||||
boolean presentInBody = url.isPresent() && Stream.of(LinkPreviewUtil.findValidPreviewUrls(message)).map(Link::getUrl).collect(Collectors.toSet()).contains(url.get());
|
||||
boolean validDomain = url.isPresent() && LinkPreviewUtil.isValidPreviewUrl(url.get());
|
||||
|
||||
if (hasContent && presentInBody && validDomain) {
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package org.thoughtcrime.securesms.keyvalue;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public final class SettingsValues extends SignalStoreValues {
|
||||
|
||||
public static final String LINK_PREVIEWS = "settings.link_previews";
|
||||
|
||||
SettingsValues(@NonNull KeyValueStore store) {
|
||||
super(store);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onFirstEverAppLaunch() {
|
||||
getStore().beginWrite()
|
||||
.putBoolean(LINK_PREVIEWS, true)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public boolean isLinkPreviewsEnabled() {
|
||||
return getBoolean(LINK_PREVIEWS, false);
|
||||
}
|
||||
|
||||
public void setLinkPreviewsEnabled(boolean enabled) {
|
||||
putBoolean(LINK_PREVIEWS, enabled);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ public final class SignalStore {
|
|||
private final MiscellaneousValues misc;
|
||||
private final InternalValues internalValues;
|
||||
private final EmojiValues emojiValues;
|
||||
private final SettingsValues settingsValues;
|
||||
|
||||
private SignalStore() {
|
||||
this.store = ApplicationDependencies.getKeyValueStore();
|
||||
|
@ -37,6 +38,7 @@ public final class SignalStore {
|
|||
this.misc = new MiscellaneousValues(store);
|
||||
this.internalValues = new InternalValues(store);
|
||||
this.emojiValues = new EmojiValues(store);
|
||||
this.settingsValues = new SettingsValues(store);
|
||||
}
|
||||
|
||||
public static void onFirstEverAppLaunch() {
|
||||
|
@ -49,6 +51,7 @@ public final class SignalStore {
|
|||
tooltips().onFirstEverAppLaunch();
|
||||
misc().onFirstEverAppLaunch();
|
||||
internalValues().onFirstEverAppLaunch();
|
||||
settings().onFirstEverAppLaunch();
|
||||
}
|
||||
|
||||
public static @NonNull KbsValues kbsValues() {
|
||||
|
@ -91,6 +94,10 @@ public final class SignalStore {
|
|||
return INSTANCE.emojiValues;
|
||||
}
|
||||
|
||||
public static @NonNull SettingsValues settings() {
|
||||
return INSTANCE.settingsValues;
|
||||
}
|
||||
|
||||
public static @NonNull GroupsV2AuthorizationSignalStoreCache groupsV2AuthorizationCache() {
|
||||
return new GroupsV2AuthorizationSignalStoreCache(getStore());
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public final class LinkPreviewUtil {
|
|||
/**
|
||||
* @return All whitelisted URLs in the source text.
|
||||
*/
|
||||
public static @NonNull List<Link> findWhitelistedUrls(@NonNull String text) {
|
||||
public static @NonNull List<Link> findValidPreviewUrls(@NonNull String text) {
|
||||
SpannableString spannable = new SpannableString(text);
|
||||
boolean found = Linkify.addLinks(spannable, Linkify.WEB_URLS);
|
||||
|
||||
|
|
|
@ -41,6 +41,10 @@ public class LinkPreviewViewModel extends ViewModel {
|
|||
return linkPreviewState.getValue() != null && linkPreviewState.getValue().getLinkPreview().isPresent();
|
||||
}
|
||||
|
||||
public boolean hasLinkPreviewUi() {
|
||||
return linkPreviewState.getValue() != null && linkPreviewState.getValue().hasContent();
|
||||
}
|
||||
|
||||
public @NonNull List<LinkPreview> getActiveLinkPreviews() {
|
||||
final LinkPreviewState state = linkPreviewState.getValue();
|
||||
|
||||
|
@ -61,7 +65,7 @@ public class LinkPreviewViewModel extends ViewModel {
|
|||
return;
|
||||
}
|
||||
|
||||
List<Link> links = LinkPreviewUtil.findWhitelistedUrls(text);
|
||||
List<Link> links = LinkPreviewUtil.findValidPreviewUrls(text);
|
||||
Optional<Link> link = links.isEmpty() ? Optional.absent() : Optional.of(links.get(0));
|
||||
|
||||
if (link.isPresent() && link.get().getUrl().equals(activeUrl)) {
|
||||
|
@ -75,7 +79,7 @@ public class LinkPreviewViewModel extends ViewModel {
|
|||
|
||||
if (!link.isPresent() || !isCursorPositionValid(text, link.get(), cursorStart, cursorEnd)) {
|
||||
activeUrl = null;
|
||||
linkPreviewState.setValue(LinkPreviewState.forEmpty());
|
||||
linkPreviewState.setValue(LinkPreviewState.forNoLinks());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -85,7 +89,11 @@ public class LinkPreviewViewModel extends ViewModel {
|
|||
activeRequest = repository.getLinkPreview(context, link.get().getUrl(), lp -> {
|
||||
Util.runOnMain(() -> {
|
||||
if (!userCanceled) {
|
||||
linkPreviewState.setValue(LinkPreviewState.forPreview(lp));
|
||||
if (lp.isPresent()) {
|
||||
linkPreviewState.setValue(LinkPreviewState.forPreview(lp.get()));
|
||||
} else {
|
||||
linkPreviewState.setValue(LinkPreviewState.forLinksWithNoPreview());
|
||||
}
|
||||
}
|
||||
activeRequest = null;
|
||||
});
|
||||
|
@ -103,7 +111,7 @@ public class LinkPreviewViewModel extends ViewModel {
|
|||
activeUrl = null;
|
||||
|
||||
debouncer.clear();
|
||||
linkPreviewState.setValue(LinkPreviewState.forEmpty());
|
||||
linkPreviewState.setValue(LinkPreviewState.forNoLinks());
|
||||
}
|
||||
|
||||
public void onEnabled() {
|
||||
|
@ -133,32 +141,46 @@ public class LinkPreviewViewModel extends ViewModel {
|
|||
|
||||
public static class LinkPreviewState {
|
||||
private final boolean isLoading;
|
||||
private final boolean hasLinks;
|
||||
private final Optional<LinkPreview> linkPreview;
|
||||
|
||||
private LinkPreviewState(boolean isLoading, Optional<LinkPreview> linkPreview) {
|
||||
private LinkPreviewState(boolean isLoading, boolean hasLinks, Optional<LinkPreview> linkPreview) {
|
||||
this.isLoading = isLoading;
|
||||
this.hasLinks = hasLinks;
|
||||
this.linkPreview = linkPreview;
|
||||
}
|
||||
|
||||
private static LinkPreviewState forLoading() {
|
||||
return new LinkPreviewState(true, Optional.absent());
|
||||
return new LinkPreviewState(true, false, Optional.absent());
|
||||
}
|
||||
|
||||
private static LinkPreviewState forPreview(@NonNull Optional<LinkPreview> linkPreview) {
|
||||
return new LinkPreviewState(false, linkPreview);
|
||||
private static LinkPreviewState forPreview(@NonNull LinkPreview linkPreview) {
|
||||
return new LinkPreviewState(false, true, Optional.of(linkPreview));
|
||||
}
|
||||
|
||||
private static LinkPreviewState forEmpty() {
|
||||
return new LinkPreviewState(false, Optional.absent());
|
||||
private static LinkPreviewState forLinksWithNoPreview() {
|
||||
return new LinkPreviewState(false, true, Optional.absent());
|
||||
}
|
||||
|
||||
private static LinkPreviewState forNoLinks() {
|
||||
return new LinkPreviewState(false, false, Optional.absent());
|
||||
}
|
||||
|
||||
public boolean isLoading() {
|
||||
return isLoading;
|
||||
}
|
||||
|
||||
public boolean hasLinks() {
|
||||
return hasLinks;
|
||||
}
|
||||
|
||||
public Optional<LinkPreview> getLinkPreview() {
|
||||
return linkPreview;
|
||||
}
|
||||
|
||||
boolean hasContent() {
|
||||
return isLoading || hasLinks;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory extends ViewModelProvider.NewInstanceFactory {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.thoughtcrime.securesms.linkpreview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.megaphone.Megaphone;
|
||||
import org.thoughtcrime.securesms.megaphone.MegaphoneActionController;
|
||||
|
||||
public class LinkPreviewsMegaphoneView extends FrameLayout {
|
||||
|
||||
private View yesButton;
|
||||
private View noButton;
|
||||
|
||||
public LinkPreviewsMegaphoneView(Context context) {
|
||||
super(context);
|
||||
initialize(context);
|
||||
}
|
||||
|
||||
public LinkPreviewsMegaphoneView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initialize(context);
|
||||
}
|
||||
|
||||
private void initialize(@NonNull Context context) {
|
||||
inflate(context, R.layout.link_previews_megaphone, this);
|
||||
|
||||
this.yesButton = findViewById(R.id.linkpreview_megaphone_ok);
|
||||
this.noButton = findViewById(R.id.linkpreview_megaphone_disable);
|
||||
}
|
||||
|
||||
public void present(@NonNull Megaphone megaphone, @NonNull MegaphoneActionController listener) {
|
||||
this.yesButton.setOnClickListener(v -> {
|
||||
SignalStore.settings().setLinkPreviewsEnabled(true);
|
||||
listener.onMegaphoneCompleted(megaphone.getEvent());
|
||||
});
|
||||
|
||||
this.noButton.setOnClickListener(v -> {
|
||||
SignalStore.settings().setLinkPreviewsEnabled(false);
|
||||
listener.onMegaphoneCompleted(megaphone.getEvent());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -172,6 +172,9 @@ public class Megaphone {
|
|||
/** Specialized style for announcing reactions. */
|
||||
REACTIONS,
|
||||
|
||||
/** Specialized style for announcing link previews. */
|
||||
LINK_PREVIEWS,
|
||||
|
||||
/** Basic bottom of the screen megaphone with optional snooze and action buttons. */
|
||||
BASIC,
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.view.View;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewsMegaphoneView;
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsMegaphoneView;
|
||||
|
||||
public class MegaphoneViewBuilder {
|
||||
|
@ -21,6 +22,8 @@ public class MegaphoneViewBuilder {
|
|||
return null;
|
||||
case REACTIONS:
|
||||
return buildReactionsMegaphone(context, megaphone, listener);
|
||||
case LINK_PREVIEWS:
|
||||
return buildLinkPreviewsMegaphone(context, megaphone, listener);
|
||||
case POPUP:
|
||||
return buildPopupMegaphone(context, megaphone, listener);
|
||||
default:
|
||||
|
@ -46,6 +49,15 @@ public class MegaphoneViewBuilder {
|
|||
return view;
|
||||
}
|
||||
|
||||
private static @NonNull View buildLinkPreviewsMegaphone(@NonNull Context context,
|
||||
@NonNull Megaphone megaphone,
|
||||
@NonNull MegaphoneActionController listener)
|
||||
{
|
||||
LinkPreviewsMegaphoneView view = new LinkPreviewsMegaphoneView(context);
|
||||
view.present(megaphone, listener);
|
||||
return view;
|
||||
}
|
||||
|
||||
private static @NonNull View buildPopupMegaphone(@NonNull Context context,
|
||||
@NonNull Megaphone megaphone,
|
||||
@NonNull MegaphoneActionController listener)
|
||||
|
|
|
@ -91,6 +91,7 @@ public final class Megaphones {
|
|||
put(Event.PIN_REMINDER, new SignalPinReminderSchedule());
|
||||
put(Event.MESSAGE_REQUESTS, shouldShowMessageRequestsMegaphone() ? ALWAYS : NEVER);
|
||||
put(Event.MENTIONS, shouldShowMentionsMegaphone() ? ALWAYS : NEVER);
|
||||
put(Event.LINK_PREVIEWS, SignalStore.settings().isLinkPreviewsEnabled() ? NEVER : ALWAYS);
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -106,6 +107,8 @@ public final class Megaphones {
|
|||
return buildMessageRequestsMegaphone(context);
|
||||
case MENTIONS:
|
||||
return buildMentionsMegaphone();
|
||||
case LINK_PREVIEWS:
|
||||
return buildLinkPreviewsMegaphone();
|
||||
default:
|
||||
throw new IllegalArgumentException("Event not handled!");
|
||||
}
|
||||
|
@ -196,6 +199,12 @@ public final class Megaphones {
|
|||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull Megaphone buildLinkPreviewsMegaphone() {
|
||||
return new Megaphone.Builder(Event.LINK_PREVIEWS, Megaphone.Style.LINK_PREVIEWS)
|
||||
.setMandatory(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static boolean shouldShowMessageRequestsMegaphone() {
|
||||
return Recipient.self().getProfileName() == ProfileName.EMPTY;
|
||||
}
|
||||
|
@ -209,7 +218,8 @@ public final class Megaphones {
|
|||
PINS_FOR_ALL("pins_for_all"),
|
||||
PIN_REMINDER("pin_reminder"),
|
||||
MESSAGE_REQUESTS("message_requests"),
|
||||
MENTIONS("mentions");
|
||||
MENTIONS("mentions"),
|
||||
LINK_PREVIEWS("link_previews");
|
||||
|
||||
private final String key;
|
||||
|
||||
|
|
|
@ -38,12 +38,15 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceConfigurationUpdateJob;
|
|||
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.KbsValues;
|
||||
import org.thoughtcrime.securesms.keyvalue.PinValues;
|
||||
import org.thoughtcrime.securesms.keyvalue.SettingsValues;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.lock.PinHashing;
|
||||
import org.thoughtcrime.securesms.lock.v2.CreateKbsPinActivity;
|
||||
import org.thoughtcrime.securesms.lock.v2.KbsConstants;
|
||||
import org.thoughtcrime.securesms.lock.v2.RegistrationLockUtil;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
|
||||
import org.thoughtcrime.securesms.megaphone.Megaphones;
|
||||
import org.thoughtcrime.securesms.pin.RegistrationLockV2Dialog;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
|
@ -90,13 +93,18 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||
this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF).setOnPreferenceClickListener(new PassphraseIntervalClickListener());
|
||||
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(PREFERENCE_CATEGORY_BLOCKED).setOnPreferenceClickListener(new BlockedContactsClickListener());
|
||||
this.findPreference(TextSecurePreferences.SHOW_UNIDENTIFIED_DELIVERY_INDICATORS).setOnPreferenceChangeListener(new ShowUnidentifiedDeliveryIndicatorsChangedListener());
|
||||
this.findPreference(TextSecurePreferences.UNIVERSAL_UNIDENTIFIED_ACCESS).setOnPreferenceChangeListener(new UniversalUnidentifiedAccessChangedListener());
|
||||
this.findPreference(PREFERENCE_UNIDENTIFIED_LEARN_MORE).setOnPreferenceClickListener(new UnidentifiedLearnMoreClickListener());
|
||||
disablePassphrase.setOnPreferenceChangeListener(new DisablePassphraseClickListener());
|
||||
|
||||
|
||||
SwitchPreferenceCompat linkPreviewPref = (SwitchPreferenceCompat) this.findPreference(SettingsValues.LINK_PREVIEWS);
|
||||
linkPreviewPref.setChecked(SignalStore.settings().isLinkPreviewsEnabled());
|
||||
linkPreviewPref.setPreferenceDataStore(SignalStore.getPreferenceDataStore());
|
||||
linkPreviewPref.setOnPreferenceChangeListener(new LinkPreviewToggleListener());
|
||||
|
||||
initializeVisibility();
|
||||
}
|
||||
|
||||
|
@ -241,7 +249,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||
ApplicationDependencies.getJobManager().add(new MultiDeviceConfigurationUpdateJob(enabled,
|
||||
TextSecurePreferences.isTypingIndicatorsEnabled(requireContext()),
|
||||
TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(getContext()),
|
||||
TextSecurePreferences.isLinkPreviewsEnabled(getContext())));
|
||||
SignalStore.settings().isLinkPreviewsEnabled()));
|
||||
|
||||
});
|
||||
return true;
|
||||
|
@ -258,7 +266,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||
ApplicationDependencies.getJobManager().add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(requireContext()),
|
||||
enabled,
|
||||
TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(getContext()),
|
||||
TextSecurePreferences.isLinkPreviewsEnabled(getContext())));
|
||||
SignalStore.settings().isLinkPreviewsEnabled()));
|
||||
|
||||
if (!enabled) {
|
||||
ApplicationContext.getInstance(requireContext()).getTypingStatusRepository().clear();
|
||||
|
@ -279,6 +287,9 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||
TextSecurePreferences.isTypingIndicatorsEnabled(requireContext()),
|
||||
TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(requireContext()),
|
||||
enabled));
|
||||
if (enabled) {
|
||||
ApplicationDependencies.getMegaphoneRepository().markFinished(Megaphones.Event.LINK_PREVIEWS);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
@ -383,7 +394,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
|||
ApplicationDependencies.getJobManager().add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(getContext()),
|
||||
TextSecurePreferences.isTypingIndicatorsEnabled(getContext()),
|
||||
enabled,
|
||||
TextSecurePreferences.isLinkPreviewsEnabled(getContext())));
|
||||
SignalStore.settings().isLinkPreviewsEnabled()));
|
||||
});
|
||||
|
||||
return true;
|
||||
|
|
|
@ -394,7 +394,7 @@ public final class StorageSyncHelper {
|
|||
.setTypingIndicatorsEnabled(TextSecurePreferences.isTypingIndicatorsEnabled(context))
|
||||
.setReadReceiptsEnabled(TextSecurePreferences.isReadReceiptsEnabled(context))
|
||||
.setSealedSenderIndicatorsEnabled(TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(context))
|
||||
.setLinkPreviewsEnabled(TextSecurePreferences.isLinkPreviewsEnabled(context))
|
||||
.setLinkPreviewsEnabled(SignalStore.settings().isLinkPreviewsEnabled())
|
||||
.build();
|
||||
|
||||
return SignalStorageRecord.forAccount(account);
|
||||
|
@ -414,7 +414,7 @@ public final class StorageSyncHelper {
|
|||
TextSecurePreferences.setReadReceiptsEnabled(context, update.isReadReceiptsEnabled());
|
||||
TextSecurePreferences.setTypingIndicatorsEnabled(context, update.isTypingIndicatorsEnabled());
|
||||
TextSecurePreferences.setShowUnidentifiedDeliveryIndicatorsEnabled(context, update.isSealedSenderIndicatorsEnabled());
|
||||
TextSecurePreferences.setLinkPreviewsEnabled(context, update.isLinkPreviewsEnabled());
|
||||
SignalStore.settings().setLinkPreviewsEnabled(update.isLinkPreviewsEnabled());
|
||||
|
||||
if (fetchProfile && update.getAvatarUrlPath().isPresent()) {
|
||||
ApplicationDependencies.getJobManager().add(new RetrieveProfileAvatarJob(Recipient.self(), update.getAvatarUrlPath().get()));
|
||||
|
|
|
@ -419,10 +419,6 @@ public class TextSecurePreferences {
|
|||
setBooleanPreference(context, TYPING_INDICATORS, enabled);
|
||||
}
|
||||
|
||||
public static boolean isLinkPreviewsEnabled(Context context) {
|
||||
return getBooleanPreference(context, LINK_PREVIEWS, true);
|
||||
}
|
||||
|
||||
public static void setLinkPreviewsEnabled(Context context, boolean enabled) {
|
||||
setBooleanPreference(context, LINK_PREVIEWS, enabled);
|
||||
}
|
||||
|
|
27
app/src/main/res/drawable/ic_megaphone_link_previews.xml
Normal file
27
app/src/main/res/drawable/ic_megaphone_link_previews.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="64"
|
||||
android:viewportHeight="64">
|
||||
<path
|
||||
android:pathData="M4,0L60,0A4,4 0,0 1,64 4L64,60A4,4 0,0 1,60 64L4,64A4,4 0,0 1,0 60L0,4A4,4 0,0 1,4 0z"
|
||||
android:fillColor="#B9B9B9"/>
|
||||
<path
|
||||
android:pathData="M9.5,54L46.5,54A1.5,1.5 0,0 1,48 55.5L48,55.5A1.5,1.5 0,0 1,46.5 57L9.5,57A1.5,1.5 0,0 1,8 55.5L8,55.5A1.5,1.5 0,0 1,9.5 54z"
|
||||
android:fillColor="#F6F6F6"/>
|
||||
<path
|
||||
android:pathData="M9.5,47L54.5,47A1.5,1.5 0,0 1,56 48.5L56,48.5A1.5,1.5 0,0 1,54.5 50L9.5,50A1.5,1.5 0,0 1,8 48.5L8,48.5A1.5,1.5 0,0 1,9.5 47z"
|
||||
android:fillColor="#F6F6F6"/>
|
||||
<path
|
||||
android:pathData="M0,4C0,1.7909 1.7909,0 4,0H60C62.2091,0 64,1.7909 64,4V41H0V4Z"
|
||||
android:fillColor="#2C6BED"/>
|
||||
<path
|
||||
android:pathData="M16.6154,10.3077m-5.5385,0a5.5385,5.5385 0,1 1,11.0769 0a5.5385,5.5385 0,1 1,-11.0769 0"
|
||||
android:fillColor="#E9E9E9"/>
|
||||
<path
|
||||
android:pathData="M11.0126,20.8283C6.3833,20.6538 2.8877,20.8738 0,21.3893V41H64V30.4162C36.7234,28.2829 21.4363,21.2214 11.0126,20.8283Z"
|
||||
android:fillColor="#6191F3"/>
|
||||
<path
|
||||
android:pathData="M-0,41L-0,37.3314C19.2247,32.4502 29.3199,15.9214 49.8461,16.4615C54.8182,16.5924 59.5815,17.6245 64,19.1928V41H-0Z"
|
||||
android:fillColor="#7DA8FF"/>
|
||||
</vector>
|
|
@ -84,18 +84,31 @@
|
|||
<com.pnikosis.materialishprogress.ProgressWheel
|
||||
android:id="@+id/linkpreview_progress_wheel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:indeterminate="true"
|
||||
android:padding="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/linkpreview_divider"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/linkpreview_no_preview"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/linkpreview_no_preview"
|
||||
app:matProg_barColor="@color/core_ultramarine"
|
||||
app:matProg_progressIndeterminate="true" />
|
||||
app:matProg_progressIndeterminate="true"
|
||||
app:matProg_barWidth="3dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/linkpreview_no_preview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/LinkPreviewView_no_link_preview_available"
|
||||
android:gravity="center"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/linkpreview_divider"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
91
app/src/main/res/layout/link_previews_megaphone.xml
Normal file
91
app/src/main/res/layout/link_previews_megaphone.xml
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="14dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
tools:parentTag="android.widget.FrameLayout">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:background="?megaphone_background"
|
||||
android:clickable="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/linkpreview_megaphone_image"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:scaleType="centerInside"
|
||||
app:srcCompat="@drawable/ic_megaphone_link_previews"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/linkpreview_megaphone_title"
|
||||
style="@style/Signal.Text.Body"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:text="@string/LinkPreviewsMegaphone_preview_any_link"
|
||||
app:layout_constraintStart_toEndOf="@id/linkpreview_megaphone_image"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/linkpreview_megaphone_image" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/linkpreview_megaphone_body"
|
||||
style="@style/Signal.Text.Preview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textColor="?megaphone_body_text_color"
|
||||
android:text="@string/LinkPreviewsMegaphone_you_can_now_retrieve_link_previews_directly_from_any_website"
|
||||
app:layout_constraintStart_toStartOf="@id/linkpreview_megaphone_title"
|
||||
app:layout_constraintTop_toBottomOf="@id/linkpreview_megaphone_title"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/linkpreview_megaphone_content_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="linkpreview_megaphone_image,linkpreview_megaphone_body,linkpreview_megaphone_title"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/linkpreview_megaphone_ok"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
style="@style/Button.Borderless"
|
||||
android:text="@string/ok"
|
||||
app:layout_constraintStart_toEndOf="@id/linkpreview_megaphone_disable"
|
||||
app:layout_constraintTop_toBottomOf="@id/linkpreview_megaphone_content_barrier"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/linkpreview_megaphone_disable"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/LinkPreviewsMegaphone_disable"
|
||||
style="@style/Button.Borderless"
|
||||
app:layout_constraintTop_toBottomOf="@id/linkpreview_megaphone_content_barrier"
|
||||
app:layout_constraintEnd_toStartOf="@id/linkpreview_megaphone_ok"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</merge>
|
|
@ -484,6 +484,14 @@
|
|||
<string name="GroupManagement_learn_more">Learn more</string>
|
||||
<string name="GroupManagement_invite_multiple_users">These users can’t be automatically added to this group by you.\n\nThey’ve been invited to join the group, and won’t see any group messages until they accept.</string>
|
||||
|
||||
<!-- LinkPreviewsMegaphone -->
|
||||
<string name="LinkPreviewsMegaphone_disable">Disable</string>
|
||||
<string name="LinkPreviewsMegaphone_preview_any_link">Preview any link</string>
|
||||
<string name="LinkPreviewsMegaphone_you_can_now_retrieve_link_previews_directly_from_any_website">You can now retrieve link previews directly from any website for messages you send.</string>
|
||||
|
||||
<!-- LinkPreviewView -->
|
||||
<string name="LinkPreviewView_no_link_preview_available">No link preview available</string>
|
||||
|
||||
<!-- PendingMembersActivity -->
|
||||
<string name="PendingMemberInvitesActivity_pending_group_invites">Pending group invites</string>
|
||||
<string name="PendingMembersActivity_people_you_invited">People you invited</string>
|
||||
|
@ -1889,8 +1897,8 @@
|
|||
<string name="preferences__use_signal_for_viewing_and_storing_all_incoming_multimedia_messages">Use Signal for all incoming multimedia messages</string>
|
||||
<string name="preferences__pref_enter_sends_title">Enter key sends</string>
|
||||
<string name="preferences__pressing_the_enter_key_will_send_text_messages">Pressing the Enter key will send text messages</string>
|
||||
<string name="preferences__send_link_previews">Send link previews</string>
|
||||
<string name="preferences__previews_are_supported_for">Previews are supported for Imgur, Instagram, Pinterest, Reddit, and YouTube links</string>
|
||||
<string name="preferences__generate_link_previews">Generate link previews</string>
|
||||
<string name="preferences__retrieve_link_previews_from_websites_for_messages">Retrieve link previews directly from websites for messages you send.</string>
|
||||
<string name="preferences__choose_identity">Choose identity</string>
|
||||
<string name="preferences__choose_your_contact_entry_from_the_contacts_list">Choose your contact entry from the contacts list.</string>
|
||||
<string name="preferences__change_passphrase">Change passphrase</string>
|
||||
|
|
|
@ -74,9 +74,9 @@
|
|||
|
||||
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="pref_link_previews"
|
||||
android:summary="@string/preferences__previews_are_supported_for"
|
||||
android:title="@string/preferences__send_link_previews" />
|
||||
android:key="settings.link_previews"
|
||||
android:summary="@string/preferences__retrieve_link_previews_from_websites_for_messages"
|
||||
android:title="@string/preferences__generate_link_previews" />
|
||||
|
||||
<Preference
|
||||
android:key="preference_category_blocked"
|
||||
|
|
Loading…
Add table
Reference in a new issue