diff --git a/src/webview/js/generatedEs3.js b/src/webview/js/generatedEs3.js index d61840afb8f..a60f97b0be1 100644 --- a/src/webview/js/generatedEs3.js +++ b/src/webview/js/generatedEs3.js @@ -152,7 +152,7 @@ function someVisibleMessage(top, bottom) { function idFromMessage(element) { var idStr = element.getAttribute('data-msg-id'); - if (!idStr) { + if (idStr === null || idStr === undefined) { throw new Error('Bad message element'); } @@ -231,6 +231,7 @@ var sendScrollMessageIfListShort = function sendScrollMessageIfListShort() { var scrollEventsDisabled = true; var lastTouchEventTimestamp = 0; +var hasLongPressed = false; var lastTouchPositionX = -1; var lastTouchPositionY = -1; @@ -421,6 +422,12 @@ var requireAttribute = function requireAttribute(e, name) { documentBody.addEventListener('click', function (e) { e.preventDefault(); lastTouchEventTimestamp = 0; + + if (hasLongPressed) { + hasLongPressed = false; + return; + } + var target = e.target; if (!(target instanceof Element)) { @@ -495,10 +502,12 @@ var handleLongPress = function handleLongPress(target) { } lastTouchEventTimestamp = 0; + hasLongPressed = true; sendMessage({ type: 'longPress', - target: target.matches('.header') ? 'header' : 'message', - messageId: getMessageIdFromNode(target) + target: target.matches('.header') ? 'header' : target.matches('a') ? 'link' : 'message', + messageId: getMessageIdFromNode(target), + href: target.matches('a') ? requireAttribute(target, 'href') : null }); }; @@ -512,6 +521,7 @@ documentBody.addEventListener('touchstart', function (e) { lastTouchPositionX = e.changedTouches[0].pageX; lastTouchPositionY = e.changedTouches[0].pageY; lastTouchEventTimestamp = Date.now(); + hasLongPressed = false; setTimeout(function () { return handleLongPress(target); }, 500); diff --git a/src/webview/js/js.js b/src/webview/js/js.js index 18d69a4f69f..e434db8bf2f 100644 --- a/src/webview/js/js.js +++ b/src/webview/js/js.js @@ -351,6 +351,7 @@ const sendScrollMessageIfListShort = () => { let scrollEventsDisabled = true; let lastTouchEventTimestamp = 0; +let hasLongPressed = false; let lastTouchPositionX = -1; let lastTouchPositionY = -1; @@ -558,6 +559,13 @@ documentBody.addEventListener('click', (e: MouseEvent) => { e.preventDefault(); lastTouchEventTimestamp = 0; + /* Without a flag `hasLongPressed`, both the short press and the long + * press actions get triggered. See PR #3404 for more context. */ + if (hasLongPressed) { + hasLongPressed = false; + return; + } + const { target } = e; if (!(target instanceof Element)) { @@ -650,11 +658,13 @@ const handleLongPress = (target: Element) => { } lastTouchEventTimestamp = 0; + hasLongPressed = true; sendMessage({ type: 'longPress', - target: target.matches('.header') ? 'header' : 'message', + target: target.matches('.header') ? 'header' : target.matches('a') ? 'link' : 'message', messageId: getMessageIdFromNode(target), + href: target.matches('a') ? requireAttribute(target, 'href') : null, }); }; @@ -667,6 +677,7 @@ documentBody.addEventListener('touchstart', (e: TouchEvent) => { lastTouchPositionX = e.changedTouches[0].pageX; lastTouchPositionY = e.changedTouches[0].pageY; lastTouchEventTimestamp = Date.now(); + hasLongPressed = false; setTimeout(() => handleLongPress(target), 500); }); diff --git a/src/webview/webViewEventHandlers.js b/src/webview/webViewEventHandlers.js index f07c169aaab..42561f84fcb 100644 --- a/src/webview/webViewEventHandlers.js +++ b/src/webview/webViewEventHandlers.js @@ -1,9 +1,11 @@ /* @flow strict-local */ +import { Clipboard } from 'react-native'; import { emojiReactionAdd, emojiReactionRemove, queueMarkAsRead } from '../api'; import config from '../config'; import type { Dispatch, GetText, Message, Narrow } from '../types'; import type { BackgroundData } from './MessageList'; import type { ShowActionSheetWithOptions } from '../message/messageActionSheet'; +import { showToast } from '../utils/info'; import { isUrlAnImage } from '../utils/url'; import { logErrorRemotely } from '../utils/logging'; import { filterUnreadMessagesInRange } from '../utils/unread'; @@ -78,8 +80,9 @@ type MessageListEventUrl = {| type MessageListEventLongPress = {| type: 'longPress', - target: 'message' | 'header', + target: 'message' | 'header' | 'link', messageId: number, + href: string | null, |}; type MessageListEventDebug = {| @@ -151,13 +154,24 @@ const handleImage = (props: Props, src: string, messageId: number) => { } }; -const handleLongPress = (props: Props, _: GetText, isHeader: boolean, messageId: number) => { +const handleLongPress = ( + props: Props, + _: GetText, + target: 'message' | 'header' | 'link', + messageId: number, + href: string | null, +) => { + if (href !== null) { + Clipboard.setString(href); + showToast(_('Link copied to clipboard')); + return; + } const message = props.messages.find(x => x.id === messageId); if (!message) { return; } const { dispatch, showActionSheetWithOptions, backgroundData, narrow } = props; - showActionSheet(isHeader, dispatch, showActionSheetWithOptions, _, { + showActionSheet(target === 'header', dispatch, showActionSheetWithOptions, _, { backgroundData, message, narrow, @@ -188,7 +202,7 @@ export const handleMessageListEvent = (props: Props, _: GetText, event: MessageL break; case 'longPress': - handleLongPress(props, _, event.target === 'header', event.messageId); + handleLongPress(props, _, event.target, event.messageId, event.href); break; case 'url': diff --git a/static/translations/messages_ar.json b/static/translations/messages_ar.json index 919e381bea2..063bf33eb53 100644 --- a/static/translations/messages_ar.json +++ b/static/translations/messages_ar.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_bg.json b/static/translations/messages_bg.json index 072dd20cb08..8b7d4e13264 100644 --- a/static/translations/messages_bg.json +++ b/static/translations/messages_bg.json @@ -50,6 +50,7 @@ "Reply": "Отговори", "Add a reaction": "Добави реакция", "Copy to clipboard": "Копирай в клипборд", + "Link copied to clipboard": "Линкът е копиран в клипборда", "Mute topic": "Заглуши тема", "Unmute topic": "Не заглушавай тема", "Mute stream": "Заглуши канал", diff --git a/static/translations/messages_ca.json b/static/translations/messages_ca.json index 3aad115ab5d..a16100ee45b 100644 --- a/static/translations/messages_ca.json +++ b/static/translations/messages_ca.json @@ -50,6 +50,7 @@ "Reply": "Respondre", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copiar al porta-retalls", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Silenciar tema", "Unmute topic": "Unmute topic", "Mute stream": "Silenciar canal", diff --git a/static/translations/messages_cs.json b/static/translations/messages_cs.json index 17dbe72df4a..9671bbea331 100644 --- a/static/translations/messages_cs.json +++ b/static/translations/messages_cs.json @@ -50,6 +50,7 @@ "Reply": "Odpovědět", "Add a reaction": "Přidat odpověď", "Copy to clipboard": "Kopírovat do schránky", + "Link copied to clipboard": "Odkaz zkopírován do schránky", "Mute topic": "Ztlumit téma", "Unmute topic": "Zrušit ztlumení tématu", "Mute stream": "Ztlumit kanál", diff --git a/static/translations/messages_da.json b/static/translations/messages_da.json index 919e381bea2..063bf33eb53 100644 --- a/static/translations/messages_da.json +++ b/static/translations/messages_da.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_de.json b/static/translations/messages_de.json index fba482f9b53..f29f684ba83 100644 --- a/static/translations/messages_de.json +++ b/static/translations/messages_de.json @@ -50,6 +50,7 @@ "Reply": "Antworten", "Add a reaction": "Reaktion hinzufügen", "Copy to clipboard": "In die Ablage kopieren", + "Link copied to clipboard": "Link in die Ablage kopiert", "Mute topic": "Thema stummschalten", "Unmute topic": "Stummschaltung aufheben", "Mute stream": "Stream stummschalten", diff --git a/static/translations/messages_en.json b/static/translations/messages_en.json index 919e381bea2..063bf33eb53 100644 --- a/static/translations/messages_en.json +++ b/static/translations/messages_en.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_es.json b/static/translations/messages_es.json index 620448f4653..228415684e7 100644 --- a/static/translations/messages_es.json +++ b/static/translations/messages_es.json @@ -50,6 +50,7 @@ "Reply": "Responder", "Add a reaction": "Añadir una reacción", "Copy to clipboard": "Copiar al portapapeles", + "Link copied to clipboard": "Enlace copiado al portapapeles", "Mute topic": "Silenciar tema", "Unmute topic": "No silenciar el tema", "Mute stream": "Silenciar canal", diff --git a/static/translations/messages_fa.json b/static/translations/messages_fa.json index 05aed0202d5..2e72734f92f 100644 --- a/static/translations/messages_fa.json +++ b/static/translations/messages_fa.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_fi.json b/static/translations/messages_fi.json index d1fa46ac288..add498d5b27 100644 --- a/static/translations/messages_fi.json +++ b/static/translations/messages_fi.json @@ -50,6 +50,7 @@ "Reply": "Vastaa", "Add a reaction": "Add a reaction", "Copy to clipboard": "Kopioi leikepöydälle", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mykistä aihe", "Unmute topic": "Poista aiheen mykistys", "Mute stream": "Mykistä kanava", diff --git a/static/translations/messages_fr.json b/static/translations/messages_fr.json index a76434ab86b..d17abf0eb3e 100644 --- a/static/translations/messages_fr.json +++ b/static/translations/messages_fr.json @@ -50,6 +50,7 @@ "Reply": "Répondre", "Add a reaction": "Ajouter une réaction", "Copy to clipboard": "Copier dans le presse-papier", + "Link copied to clipboard": "Lien copié vers le presse-papier", "Mute topic": "Rendre le sujet muet", "Unmute topic": "Ne plus rendre le sujet muet", "Mute stream": "Rendre le canal muet ", diff --git a/static/translations/messages_gl.json b/static/translations/messages_gl.json index 00f371b4295..f937396c78b 100644 --- a/static/translations/messages_gl.json +++ b/static/translations/messages_gl.json @@ -50,6 +50,7 @@ "Reply": "Responder", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copiar no portarretallos", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Silenciar este tema", "Unmute topic": "Deixar de silenciar este tema", "Mute stream": "Silenciar o fío", diff --git a/static/translations/messages_hi.json b/static/translations/messages_hi.json index 948db0e46c6..9ddffd6c2cc 100644 --- a/static/translations/messages_hi.json +++ b/static/translations/messages_hi.json @@ -50,6 +50,7 @@ "Reply": "जवाब दें", "Add a reaction": "एक प्रतिक्रिया जोड़ें", "Copy to clipboard": "क्लिपबोर्ड पर कॉपी करें", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "विषय म्यूट करें", "Unmute topic": "विषय अनम्यूट करें", "Mute stream": " धारा म्यूट करें", diff --git a/static/translations/messages_hr.json b/static/translations/messages_hr.json index 919e381bea2..063bf33eb53 100644 --- a/static/translations/messages_hr.json +++ b/static/translations/messages_hr.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_hu.json b/static/translations/messages_hu.json index 79a184252ca..3ecafa8bae7 100644 --- a/static/translations/messages_hu.json +++ b/static/translations/messages_hu.json @@ -50,6 +50,7 @@ "Reply": "Válasz", "Add a reaction": "Add a reaction", "Copy to clipboard": "Másolás vágólapra", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Téma némítása", "Unmute topic": "Téma némítás feloldása", "Mute stream": "Üzenetfolyam némítása", diff --git a/static/translations/messages_id_ID.json b/static/translations/messages_id_ID.json index 1192f3245d6..f0bfa16556b 100644 --- a/static/translations/messages_id_ID.json +++ b/static/translations/messages_id_ID.json @@ -50,6 +50,7 @@ "Reply": "Balas", "Add a reaction": "Add a reaction", "Copy to clipboard": "Salin ke clipboard", + "Link copied to clipboard": "Tautan disalin ke clipboard", "Mute topic": "Senyapkan topik", "Unmute topic": "Nyalakan topik", "Mute stream": "Senyapkan stream", diff --git a/static/translations/messages_it.json b/static/translations/messages_it.json index 1c99bdd6d90..fbc4f684444 100644 --- a/static/translations/messages_it.json +++ b/static/translations/messages_it.json @@ -50,6 +50,7 @@ "Reply": "Rispondi", "Add a reaction": "Aggiungi una reazione", "Copy to clipboard": "Copia negli appunti", + "Link copied to clipboard": "Link copiato negli appunti", "Mute topic": "Silenzia il topic", "Unmute topic": "Riattiva audio dell'argomento", "Mute stream": "Zittisci il canale", diff --git a/static/translations/messages_ja.json b/static/translations/messages_ja.json index 601565ab42d..71e83976bf1 100644 --- a/static/translations/messages_ja.json +++ b/static/translations/messages_ja.json @@ -50,6 +50,7 @@ "Reply": "返信", "Add a reaction": "Add a reaction", "Copy to clipboard": "クリップボードにコピー", + "Link copied to clipboard": "リンクをクリップボードにコピー", "Mute topic": "トピックをミュート", "Unmute topic": "トピックのミュートを解除", "Mute stream": "ストリームをミュート", diff --git a/static/translations/messages_ko.json b/static/translations/messages_ko.json index ab0a0f96d7e..3216b298987 100644 --- a/static/translations/messages_ko.json +++ b/static/translations/messages_ko.json @@ -50,6 +50,7 @@ "Reply": "답장", "Add a reaction": "반응 추가", "Copy to clipboard": "클립보드에 복사하기", + "Link copied to clipboard": "링크가 클립보드에 복사되었습니다.", "Mute topic": "주제 뮤트하기", "Unmute topic": "주제 언뮤트하기", "Mute stream": "스트림 뮤트하기", diff --git a/static/translations/messages_ml.json b/static/translations/messages_ml.json index 32e7ac2c762..ce4116211e7 100644 --- a/static/translations/messages_ml.json +++ b/static/translations/messages_ml.json @@ -50,6 +50,7 @@ "Reply": "മറുപടി", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_nl.json b/static/translations/messages_nl.json index cd3f76480c3..81eb73fc4ac 100644 --- a/static/translations/messages_nl.json +++ b/static/translations/messages_nl.json @@ -50,6 +50,7 @@ "Reply": "Antwoorden", "Add a reaction": "Add a reaction", "Copy to clipboard": "Kopiëren", + "Link copied to clipboard": "Link gekopieerd naar klembord", "Mute topic": "Onderwerp dempen", "Unmute topic": "Onderwerp aanzetten", "Mute stream": "Kanaal dempen", diff --git a/static/translations/messages_pl.json b/static/translations/messages_pl.json index cddf1e3a996..37842021c16 100644 --- a/static/translations/messages_pl.json +++ b/static/translations/messages_pl.json @@ -50,6 +50,7 @@ "Reply": "Odpowiedz", "Add a reaction": "Dodaj reakcje", "Copy to clipboard": "Kopiuj do schowka", + "Link copied to clipboard": "Link skopiowany do schowka", "Mute topic": "Wycisz wątek", "Unmute topic": "Przywróć powiadomienia w wątku", "Mute stream": "Wycisz kanał", diff --git a/static/translations/messages_pt.json b/static/translations/messages_pt.json index e6529c52085..6ce50379e70 100644 --- a/static/translations/messages_pt.json +++ b/static/translations/messages_pt.json @@ -50,6 +50,7 @@ "Reply": "Responder", "Add a reaction": "Adicionar uma reação", "Copy to clipboard": "Copiar para área de transferência", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Silenciar tópico", "Unmute topic": "Cancelar o silenciamento do tópico", "Mute stream": "Silenciar fluxo", diff --git a/static/translations/messages_ro.json b/static/translations/messages_ro.json index 86eb6db15fb..e544999cd8c 100644 --- a/static/translations/messages_ro.json +++ b/static/translations/messages_ro.json @@ -50,6 +50,7 @@ "Reply": "Răspunde", "Add a reaction": "Reacționează", "Copy to clipboard": "Copiere în clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Dezactivează sunetele pentru subiect", "Unmute topic": "Activează sunetele pentru subiect", "Mute stream": "Dezactivează sunetele pentru flux", diff --git a/static/translations/messages_ru.json b/static/translations/messages_ru.json index 8e98289599f..d99b7876312 100644 --- a/static/translations/messages_ru.json +++ b/static/translations/messages_ru.json @@ -50,6 +50,7 @@ "Reply": "Ответить", "Add a reaction": "Add a reaction", "Copy to clipboard": "Скопировать в буфер обмена", + "Link copied to clipboard": "Ссылка скопирована в буфер обмена", "Mute topic": "Заглушить тему", "Unmute topic": "Включить тему", "Mute stream": "Заглушить канал", diff --git a/static/translations/messages_sr.json b/static/translations/messages_sr.json index aa1933c4ba4..ece5258b546 100644 --- a/static/translations/messages_sr.json +++ b/static/translations/messages_sr.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_sv.json b/static/translations/messages_sv.json index 919e381bea2..063bf33eb53 100644 --- a/static/translations/messages_sv.json +++ b/static/translations/messages_sv.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_ta.json b/static/translations/messages_ta.json index bf1516c9256..d0a9628d825 100644 --- a/static/translations/messages_ta.json +++ b/static/translations/messages_ta.json @@ -50,6 +50,7 @@ "Reply": "மறுமொழி", "Add a reaction": "Add a reaction", "Copy to clipboard": "நகல் நினைவியை நகலெடுக்கவும்", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "தலைப்பை அமைதியாக்கு", "Unmute topic": "தலைப்பு தடையை நீக்கு", "Mute stream": "தொடரை அமைதியாக்கு", diff --git a/static/translations/messages_tr.json b/static/translations/messages_tr.json index d09b164e178..645dd1cff28 100644 --- a/static/translations/messages_tr.json +++ b/static/translations/messages_tr.json @@ -50,6 +50,7 @@ "Reply": "Yanıtla", "Add a reaction": "Tepki ekle", "Copy to clipboard": "Panoya kopyala", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Konuyu susturun", "Unmute topic": "Konunun sesini açın", "Mute stream": "Kanalı sessize al", diff --git a/static/translations/messages_uk.json b/static/translations/messages_uk.json index 895ff65016b..a723bba544b 100644 --- a/static/translations/messages_uk.json +++ b/static/translations/messages_uk.json @@ -50,6 +50,7 @@ "Reply": "Відповісти", "Add a reaction": "Додати реакцію", "Copy to clipboard": "Копіювати в буфер обміну", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Заглушити тему", "Unmute topic": "Увімкнути сповіщення теми", "Mute stream": "Заглушити канал", diff --git a/static/translations/messages_uz.json b/static/translations/messages_uz.json index 919e381bea2..063bf33eb53 100644 --- a/static/translations/messages_uz.json +++ b/static/translations/messages_uz.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream", diff --git a/static/translations/messages_zh-Hans.json b/static/translations/messages_zh-Hans.json index 54537706d95..4a07120a0c6 100644 --- a/static/translations/messages_zh-Hans.json +++ b/static/translations/messages_zh-Hans.json @@ -50,6 +50,7 @@ "Reply": "回复", "Add a reaction": "添加映射", "Copy to clipboard": "复制到剪贴板", + "Link copied to clipboard": "链接已复制到剪贴板", "Mute topic": "静音主题", "Unmute topic": "非静音主题", "Mute stream": "静音频道", diff --git a/static/translations/messages_zh-Hant.json b/static/translations/messages_zh-Hant.json index 4e9a3beebbb..57ac5e0b910 100644 --- a/static/translations/messages_zh-Hant.json +++ b/static/translations/messages_zh-Hant.json @@ -50,6 +50,7 @@ "Reply": "Reply", "Add a reaction": "Add a reaction", "Copy to clipboard": "Copy to clipboard", + "Link copied to clipboard": "Link copied to clipboard", "Mute topic": "Mute topic", "Unmute topic": "Unmute topic", "Mute stream": "Mute stream",