2020-06-22 15:51:15 +00:00
|
|
|
pragma Singleton
|
|
|
|
|
|
|
|
import QtQuick 2.13
|
2020-07-15 21:04:14 +00:00
|
|
|
import "../shared/xss.js" as XSS
|
2020-09-16 11:11:31 +00:00
|
|
|
import "../shared/polyfill.number.toLocaleString.js" as NumberPolyFill
|
2020-06-22 15:51:15 +00:00
|
|
|
|
|
|
|
QtObject {
|
|
|
|
function isHex(value) {
|
2020-08-12 03:40:25 +00:00
|
|
|
return /^(-0x|0x)?[0-9a-fA-F]*$/i.test(value)
|
2020-06-22 15:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function startsWith0x(value) {
|
|
|
|
return value.startsWith('0x')
|
|
|
|
}
|
|
|
|
|
|
|
|
function isChatKey(value) {
|
|
|
|
return startsWith0x(value) && isHex(value) && value.length === 132
|
|
|
|
}
|
2020-06-22 17:26:47 +00:00
|
|
|
|
2020-06-25 13:26:58 +00:00
|
|
|
function isValidETHNamePrefix(value) {
|
|
|
|
return !(value.trim() === "" || value.endsWith(".") || value.indexOf("..") > -1)
|
|
|
|
}
|
|
|
|
|
2020-06-22 17:26:47 +00:00
|
|
|
function isAddress(value) {
|
|
|
|
return startsWith0x(value) && isHex(value) && value.length === 42
|
|
|
|
}
|
|
|
|
|
|
|
|
function isPrivateKey(value) {
|
|
|
|
return isHex(value) && ((startsWith0x(value) && value.length === 66) ||
|
|
|
|
(!startsWith0x(value) && value.length === 64))
|
|
|
|
}
|
2020-06-22 17:57:06 +00:00
|
|
|
|
2021-03-16 19:19:48 +00:00
|
|
|
function getCurrentThemeAccountColor(color) {
|
|
|
|
const upperCaseColor = color.toUpperCase()
|
|
|
|
if (Style.current.accountColors.indexOf(upperCaseColor) > -1) {
|
|
|
|
return upperCaseColor
|
|
|
|
}
|
|
|
|
|
|
|
|
let colorIndex
|
|
|
|
if (Style.current.name === Constants.lightThemeName) {
|
|
|
|
colorIndex = Style.darkTheme.accountColors.indexOf(upperCaseColor)
|
|
|
|
} else {
|
|
|
|
colorIndex = Style.lightTheme.accountColors.indexOf(upperCaseColor)
|
|
|
|
}
|
|
|
|
if (colorIndex === -1) {
|
|
|
|
// Unknown color
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return Style.current.accountColors[colorIndex]
|
|
|
|
}
|
|
|
|
|
2021-03-23 18:15:26 +00:00
|
|
|
function getMessageWithStyle(msg, useCompactMode, isCurrentUser) {
|
|
|
|
return `<style type="text/css">` +
|
|
|
|
`p, img, a, del, code, blockquote { margin: 0; padding: 0; }` +
|
|
|
|
`code {` +
|
|
|
|
`background-color: ${Style.current.codeBackground};` +
|
|
|
|
`color: ${Style.current.white};` +
|
|
|
|
`white-space: pre;` +
|
|
|
|
`}` +
|
|
|
|
`p {` +
|
|
|
|
`line-height: 22px;` +
|
|
|
|
`}` +
|
|
|
|
`a {` +
|
|
|
|
`color: ${isCurrentUser && !useCompactMode ? Style.current.white : Style.current.textColor};` +
|
|
|
|
`}` +
|
|
|
|
`a.mention {` +
|
|
|
|
`color: ${Style.current.mentionColor};` +
|
|
|
|
`background-color: ${Style.current.mentionBgColor};` +
|
|
|
|
`text-decoration: none;` +
|
|
|
|
`}` +
|
|
|
|
`del {` +
|
|
|
|
`text-decoration: line-through;` +
|
|
|
|
`}` +
|
|
|
|
`table.blockquote td {` +
|
|
|
|
`padding-left: 10px;` +
|
|
|
|
`color: ${isCurrentUser ? Style.current.chatReplyCurrentUser : Style.current.secondaryText};` +
|
|
|
|
`}` +
|
|
|
|
`table.blockquote td.quoteline {` +
|
|
|
|
`background-color: ${isCurrentUser ? Style.current.chatReplyCurrentUser : Style.current.secondaryText};` +
|
|
|
|
`height: 100%;` +
|
|
|
|
`padding-left: 0;` +
|
|
|
|
`}` +
|
|
|
|
`.emoji {` +
|
|
|
|
`vertical-align: bottom;` +
|
|
|
|
`}` +
|
|
|
|
`</style>` +
|
|
|
|
`${msg}`
|
|
|
|
}
|
|
|
|
|
2021-02-17 16:31:59 +00:00
|
|
|
function getAppSectionIndex(section) {
|
|
|
|
let sectionId = -1
|
|
|
|
switch (section) {
|
|
|
|
case Constants.chat: sectionId = 0; break;
|
|
|
|
case Constants.wallet: sectionId = 1; break;
|
|
|
|
case Constants.browser: sectionId = 2; break;
|
|
|
|
case Constants.timeline: sectionId = 3; break;
|
|
|
|
case Constants.profile: sectionId = 4; break;
|
|
|
|
case Constants.node: sectionId = 5; break;
|
|
|
|
case Constants.ui: sectionId = 6; break;
|
|
|
|
case Constants.community: sectionId = 99; break;
|
|
|
|
}
|
|
|
|
if (sectionId === -1) {
|
|
|
|
throw new Exception ("Unknown section name. Check the Constants to know the available ones")
|
|
|
|
}
|
|
|
|
return sectionId
|
|
|
|
}
|
|
|
|
|
2021-02-10 20:37:17 +00:00
|
|
|
function getDisplayName(publicKey, contactIndex) {
|
|
|
|
if (contactIndex === undefined) {
|
|
|
|
contactIndex = profileModel.contacts.list.getContactIndexByPubkey(publicKey)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (contactIndex === -1) {
|
|
|
|
return utilsModel.generateAlias(publicKey)
|
|
|
|
}
|
|
|
|
const ensVerified = profileModel.contacts.list.rowData(contactIndex, 'ensVerified')
|
|
|
|
if (!ensVerified) {
|
|
|
|
const nickname = profileModel.contacts.list.rowData(contactIndex, 'localNickname')
|
|
|
|
if (nickname) {
|
|
|
|
return nickname
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return profileModel.contacts.list.rowData(contactIndex, 'name')
|
|
|
|
}
|
|
|
|
|
2020-06-22 17:57:06 +00:00
|
|
|
function isMnemonic(value) {
|
2020-07-27 15:11:24 +00:00
|
|
|
if(!value.match(/^([a-z\s]+)$/)){
|
|
|
|
return false;
|
|
|
|
}
|
2021-04-12 15:40:49 +00:00
|
|
|
return Utils.seedPhraseValidWordCount(value);
|
2020-06-22 17:57:06 +00:00
|
|
|
}
|
2020-06-25 13:26:58 +00:00
|
|
|
|
|
|
|
function compactAddress(addr, numberOfChars) {
|
|
|
|
if(addr.length <= 5 + (numberOfChars * 2)){ // 5 represents these chars 0x...
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
return addr.substring(0, 2 + numberOfChars) + "..." + addr.substring(addr.length - numberOfChars);
|
|
|
|
}
|
2020-07-15 21:04:14 +00:00
|
|
|
|
|
|
|
function linkifyAndXSS(inputText) {
|
|
|
|
//URLs starting with http://, https://, or ftp://
|
2021-02-25 19:32:39 +00:00
|
|
|
var replacePattern1 = /(\b(https?|ftp|statusim):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
|
2020-07-15 21:04:14 +00:00
|
|
|
var replacedText = inputText.replace(replacePattern1, "<a href='$1'>$1</a>");
|
|
|
|
|
|
|
|
//URLs starting with "www." (without // before it, or it'd re-link the ones done above).
|
|
|
|
var replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
|
|
|
|
replacedText = replacedText.replace(replacePattern2, "$1<a href='http://$2'>$2</a>");
|
|
|
|
|
2020-11-05 20:03:53 +00:00
|
|
|
return XSS.filterXSS(replacedText)
|
|
|
|
}
|
|
|
|
|
|
|
|
function filterXSS(inputText) {
|
|
|
|
return XSS.filterXSS(inputText)
|
2020-07-15 21:04:14 +00:00
|
|
|
}
|
2020-07-27 17:30:20 +00:00
|
|
|
|
2020-09-16 11:11:31 +00:00
|
|
|
function toLocaleString(val, locale, options) {
|
|
|
|
return NumberPolyFill.toLocaleString(val, locale, options)
|
|
|
|
}
|
|
|
|
|
2020-07-27 17:30:20 +00:00
|
|
|
function isOnlyEmoji(inputText) {
|
|
|
|
var emoji_regex = /^(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff]|\s)+$/;
|
|
|
|
return emoji_regex.test(inputText);
|
2020-08-07 19:26:51 +00:00
|
|
|
}
|
2020-07-27 17:30:20 +00:00
|
|
|
|
2020-08-07 19:26:51 +00:00
|
|
|
function removeStatusEns(userName){
|
|
|
|
return userName.endsWith(".stateofus.eth") ? userName.substr(0, userName.length - 14) : userName
|
2020-07-27 17:30:20 +00:00
|
|
|
}
|
2020-08-12 03:40:25 +00:00
|
|
|
|
|
|
|
function isValidAddress(inputValue) {
|
2020-11-04 12:37:53 +00:00
|
|
|
return inputValue !== "0x" && /^0x[a-fA-F0-9]{40}$/.test(inputValue)
|
2020-08-12 03:40:25 +00:00
|
|
|
}
|
2020-08-13 08:24:51 +00:00
|
|
|
|
2020-09-09 11:04:01 +00:00
|
|
|
function isValidEns(inputValue) {
|
2020-11-04 12:37:53 +00:00
|
|
|
if (!inputValue) {
|
|
|
|
return false
|
|
|
|
}
|
2020-09-09 11:04:01 +00:00
|
|
|
const isEmail = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/.test(inputValue)
|
|
|
|
const isDomain = /(?:(?:(?<thld>[\w\-]*)(?:\.))?(?<sld>[\w\-]*))\.(?<tld>[\w\-]*)/.test(inputValue)
|
2020-11-04 12:37:53 +00:00
|
|
|
return isEmail || isDomain || (inputValue.startsWith("@") && inputValue.length > 1)
|
2020-09-09 11:04:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-13 08:24:51 +00:00
|
|
|
/**
|
|
|
|
* Removes trailing zeros from a string-representation of a number. Throws
|
|
|
|
* if parameter is not a string
|
|
|
|
*/
|
|
|
|
function stripTrailingZeros(strNumber) {
|
|
|
|
if (!(typeof strNumber === "string")) {
|
2020-09-01 03:49:05 +00:00
|
|
|
try {
|
|
|
|
strNumber = strNumber.toString()
|
|
|
|
} catch(e) {
|
|
|
|
throw "[Utils.stripTrailingZeros] input parameter must be a string"
|
|
|
|
}
|
2020-08-13 08:24:51 +00:00
|
|
|
}
|
|
|
|
return strNumber.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1')
|
|
|
|
}
|
2020-08-17 20:46:13 +00:00
|
|
|
|
2020-09-08 21:24:12 +00:00
|
|
|
/**
|
|
|
|
* Removes starting zeros from a string-representation of a number. Throws
|
|
|
|
* if parameter is not a string
|
|
|
|
*/
|
|
|
|
function stripStartingZeros(strNumber) {
|
|
|
|
if (!(typeof strNumber === "string")) {
|
|
|
|
try {
|
|
|
|
strNumber = strNumber.toString()
|
|
|
|
} catch(e) {
|
|
|
|
throw "[Utils.stripStartingZeros] input parameter must be a string"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return strNumber.replace(/^(0*)([0-9\.]+)/, "$2")
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-17 20:46:13 +00:00
|
|
|
function setColorAlpha(color, alpha) {
|
|
|
|
return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
|
|
|
|
}
|
2020-08-26 15:15:40 +00:00
|
|
|
|
|
|
|
function formatTime(timestamp) {
|
|
|
|
let messageDate = new Date(Math.floor(timestamp))
|
|
|
|
let minutes = messageDate.getMinutes();
|
|
|
|
let hours = messageDate.getHours();
|
|
|
|
return (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes)
|
|
|
|
}
|
2020-09-01 03:49:05 +00:00
|
|
|
|
2021-01-19 20:16:42 +00:00
|
|
|
function formatShortDateStr(longStr) {
|
|
|
|
const dmKeys = {
|
|
|
|
// Days
|
2021-02-18 16:36:05 +00:00
|
|
|
//% "Sun"
|
|
|
|
Sunday: qsTrId("sun"),
|
|
|
|
//% "Mon"
|
|
|
|
Monday: qsTrId("mon"),
|
|
|
|
//% "Tue"
|
|
|
|
Tuesday: qsTrId("tue"),
|
|
|
|
//% "Wed"
|
|
|
|
Wednesday: qsTrId("wed"),
|
|
|
|
//% "Thu"
|
|
|
|
Thursday: qsTrId("thu"),
|
|
|
|
//% "Fri"
|
|
|
|
Friday: qsTrId("fri"),
|
|
|
|
//% "Sat"
|
|
|
|
Saturday: qsTrId("sat"),
|
2021-01-19 20:16:42 +00:00
|
|
|
// Months
|
2021-02-18 16:36:05 +00:00
|
|
|
//% "Jan"
|
|
|
|
January: qsTrId("jan"),
|
|
|
|
//% "Feb"
|
|
|
|
February: qsTrId("feb"),
|
|
|
|
//% "Mar"
|
|
|
|
March: qsTrId("mar"),
|
|
|
|
//% "Apr"
|
|
|
|
April: qsTrId("apr"),
|
|
|
|
//% "May"
|
|
|
|
May: qsTrId("may"),
|
|
|
|
//% "Jun"
|
|
|
|
June: qsTrId("jun"),
|
|
|
|
//% "Jul"
|
|
|
|
July: qsTrId("jul"),
|
|
|
|
//% "Aug"
|
|
|
|
August: qsTrId("aug"),
|
|
|
|
//% "Sep"
|
|
|
|
September: qsTrId("sep"),
|
|
|
|
//% "Oct"
|
|
|
|
October: qsTrId("oct"),
|
|
|
|
//% "Nov"
|
|
|
|
November: qsTrId("nov"),
|
|
|
|
//% "Dec"
|
|
|
|
December: qsTrId("dec")
|
2021-01-19 20:16:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let shortStr = longStr;
|
|
|
|
for (const [key, value] of Object.entries(dmKeys)) {
|
|
|
|
shortStr = shortStr.replace(key, value);
|
|
|
|
shortStr = shortStr.replace(key.toLowerCase(), value);
|
|
|
|
shortStr = shortStr.replace(key.toUpperCase(), value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return shortStr;
|
|
|
|
}
|
|
|
|
|
2021-01-04 14:47:25 +00:00
|
|
|
function formatDateTime(timestamp, locale) {
|
2020-12-22 10:22:04 +00:00
|
|
|
let now = new Date()
|
|
|
|
let yesterday = new Date()
|
|
|
|
yesterday.setDate(now.getDate()-1)
|
|
|
|
let messageDate = new Date(Math.floor(timestamp))
|
|
|
|
let lastWeek = new Date()
|
|
|
|
lastWeek.setDate(now.getDate()-7)
|
|
|
|
|
|
|
|
let minutes = messageDate.getMinutes();
|
|
|
|
let hours = messageDate.getHours();
|
|
|
|
|
|
|
|
if (now.toDateString() === messageDate.toDateString()) {
|
|
|
|
return (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes)
|
|
|
|
} else if (yesterday.toDateString() === messageDate.toDateString()) {
|
2021-02-18 16:36:05 +00:00
|
|
|
//% "Yesterday"
|
|
|
|
return qsTrId("yesterday")
|
2020-12-22 10:22:04 +00:00
|
|
|
} else if (lastWeek.getTime() < messageDate.getTime()) {
|
2021-02-18 16:36:05 +00:00
|
|
|
//% "Sunday"
|
|
|
|
let days = [qsTrId("sunday"),
|
|
|
|
//% "Monday"
|
|
|
|
qsTrId("monday"),
|
|
|
|
//% "Tuesday"
|
|
|
|
qsTrId("tuesday"),
|
|
|
|
//% "Wednesday"
|
|
|
|
qsTrId("wednesday"),
|
|
|
|
//% "Thursday"
|
|
|
|
qsTrId("thursday"),
|
|
|
|
//% "Friday"
|
|
|
|
qsTrId("friday"),
|
|
|
|
//% "Saturday"
|
|
|
|
qsTrId("saturday")];
|
2020-12-22 10:22:04 +00:00
|
|
|
return days[messageDate.getDay()];
|
|
|
|
} else {
|
2021-01-19 20:16:42 +00:00
|
|
|
return formatShortDateStr(new Date().toLocaleDateString(Qt.locale(locale)))
|
2020-12-22 10:22:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-01 03:49:05 +00:00
|
|
|
function findAssetBySymbol(assets, symbolToFind) {
|
|
|
|
for(var i=0; i<assets.rowCount(); i++) {
|
|
|
|
const symbol = assets.rowData(i, "symbol")
|
|
|
|
if (symbol.toLowerCase() === symbolToFind.toLowerCase()) {
|
|
|
|
return {
|
|
|
|
name: assets.rowData(i, "name"),
|
|
|
|
symbol,
|
|
|
|
value: assets.rowData(i, "value"),
|
|
|
|
fiatBalanceDisplay: assets.rowData(i, "fiatBalanceDisplay"),
|
|
|
|
address: assets.rowData(i, "address"),
|
|
|
|
fiatBalance: assets.rowData(i, "fiatBalance")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-09-24 21:41:59 +00:00
|
|
|
|
2020-11-06 19:46:21 +00:00
|
|
|
function isValidChannelName(channelName) {
|
|
|
|
return (/^[a-z0-9\-]+$/.test(channelName))
|
|
|
|
}
|
|
|
|
|
2020-10-29 15:19:27 +00:00
|
|
|
function isURL(text) {
|
|
|
|
return (/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/.test(text))
|
|
|
|
}
|
|
|
|
|
2021-04-19 10:34:03 +00:00
|
|
|
function isURLWithOptionalProtocol(text) {
|
|
|
|
return (/^(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/.test(text))
|
|
|
|
}
|
|
|
|
|
2020-12-11 20:29:46 +00:00
|
|
|
function isHexColor(c) {
|
2021-01-06 14:58:44 +00:00
|
|
|
return (/^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$/i.test(c))
|
2020-12-11 20:29:46 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 15:23:04 +00:00
|
|
|
function isSpace(c) {
|
|
|
|
return (/( |\t|\n|\r)/.test(c))
|
2020-09-24 21:41:59 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 18:45:39 +00:00
|
|
|
function getLinkTitleAndCb(link) {
|
|
|
|
const result = {
|
|
|
|
title: "Status",
|
|
|
|
callback: null
|
2021-02-25 19:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Link to send a direct message
|
|
|
|
let index = link.indexOf("/u/")
|
2021-03-05 18:45:39 +00:00
|
|
|
if (index === -1) {
|
|
|
|
// Try /p/ as well
|
|
|
|
index = link.indexOf("/p/")
|
|
|
|
}
|
2021-02-25 19:41:40 +00:00
|
|
|
if (index > -1) {
|
|
|
|
const pk = link.substring(index + 3)
|
2021-03-05 18:45:39 +00:00
|
|
|
result.title = qsTr("Start a 1 on 1 chat with %1").arg(utilsModel.generateAlias(pk))
|
|
|
|
result.callback = function () {
|
2021-02-25 19:41:40 +00:00
|
|
|
chatsModel.joinChat(pk, Constants.chatTypeOneToOne);
|
|
|
|
}
|
2021-03-05 18:45:39 +00:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-03-05 19:42:41 +00:00
|
|
|
// Community
|
|
|
|
// TODO this will probably change
|
|
|
|
index = link.lastIndexOf("/cc/")
|
|
|
|
if (index > -1) {
|
|
|
|
const communityId = link.substring(index + 4)
|
|
|
|
|
|
|
|
const communityName = chatsModel.communities.getCommunityNameById(communityId)
|
|
|
|
|
|
|
|
if (!communityName) {
|
|
|
|
// Unknown community
|
|
|
|
// TODO use a function to fetch that community?
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
result.title = qsTr("Join the %1 community").arg(communityName)
|
2021-03-08 20:21:56 +00:00
|
|
|
result.communityId = communityId
|
2021-03-05 19:42:41 +00:00
|
|
|
result.callback = function () {
|
|
|
|
const isUserMemberOfCommunity = chatsModel.communities.isUserMemberOfCommunity(communityId)
|
|
|
|
if (isUserMemberOfCommunity) {
|
|
|
|
chatsModel.communities.setActiveCommunity(communityId)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
chatsModel.communities.joinCommunity(communityId, true)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2021-03-05 18:45:39 +00:00
|
|
|
// Public chat
|
|
|
|
// This needs to be the last check because it is as VERY loose check
|
|
|
|
index = link.lastIndexOf("/")
|
|
|
|
if (index > -1) {
|
|
|
|
const chatId = link.substring(index + 1)
|
|
|
|
result.title = qsTr("Join the %1 public channel").arg(chatId)
|
|
|
|
result.callback = function () {
|
|
|
|
chatsModel.joinChat(chatId, Constants.chatTypePublic);
|
|
|
|
}
|
|
|
|
return result
|
2021-02-25 19:41:40 +00:00
|
|
|
}
|
|
|
|
|
2021-03-05 18:45:39 +00:00
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
function getLinkDataForStatusLinks(link) {
|
|
|
|
if (!link.includes(Constants.deepLinkPrefix) && !link.includes(Constants.joinStatusLink)) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = getLinkTitleAndCb(link)
|
|
|
|
|
2021-02-25 19:41:40 +00:00
|
|
|
return {
|
|
|
|
site: qsTr("Status app link"),
|
2021-03-05 18:45:39 +00:00
|
|
|
title: result.title,
|
2021-03-08 20:21:56 +00:00
|
|
|
communityId: result.communityId,
|
2021-02-25 19:41:40 +00:00
|
|
|
thumbnailUrl: "../../../../img/status.png",
|
|
|
|
contentType: "",
|
|
|
|
height: 0,
|
|
|
|
width: 0,
|
2021-03-05 18:45:39 +00:00
|
|
|
callback: result.callback
|
2021-02-25 19:41:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-03 13:53:46 +00:00
|
|
|
function getTick(wordCount) {
|
|
|
|
return (wordCount === 12 || wordCount === 15 ||
|
|
|
|
wordCount === 18 || wordCount === 21 || wordCount === 24)
|
|
|
|
? "✓ " : "";
|
|
|
|
}
|
|
|
|
|
2021-04-12 15:40:49 +00:00
|
|
|
function isValidNumberOfWords(wordCount) {
|
|
|
|
return !!getTick(wordCount);
|
|
|
|
}
|
|
|
|
|
2020-10-03 13:53:46 +00:00
|
|
|
function countWords(text) {
|
|
|
|
if (text.trim() === "")
|
|
|
|
return 0;
|
2021-04-12 15:40:49 +00:00
|
|
|
return text.trim().replace(/ +/g, " ").split(" ").length;
|
|
|
|
}
|
|
|
|
|
|
|
|
function seedPhraseValidWordCount(text) {
|
|
|
|
return isValidNumberOfWords(countWords(text))
|
2020-10-03 13:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns text in the format "✓ 12 words" for seed phrases input boxes
|
|
|
|
*/
|
|
|
|
function seedPhraseWordCountText(text) {
|
|
|
|
let wordCount = countWords(text);
|
2021-02-18 16:36:05 +00:00
|
|
|
//% "words"
|
|
|
|
return getTick(wordCount) + wordCount.toString() + " " + qsTrId("words")
|
2020-10-03 13:53:46 +00:00
|
|
|
}
|
2020-10-07 02:47:21 +00:00
|
|
|
|
|
|
|
function uuid() {
|
|
|
|
return Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
|
|
|
|
}
|
2020-11-23 20:41:57 +00:00
|
|
|
|
|
|
|
function getNetworkName(network){
|
|
|
|
switch(network){
|
2021-02-18 16:36:05 +00:00
|
|
|
//% "Mainnet with upstream RPC"
|
|
|
|
case Constants.networkMainnet: return qsTrId("mainnet-with-upstream-rpc")
|
|
|
|
//% "POA Network"
|
|
|
|
case Constants.networkPOA: return qsTrId("poa-network")
|
|
|
|
//% "xDai Chain"
|
|
|
|
case Constants.networkXDai: return qsTrId("xdai-chain")
|
|
|
|
//% "Goerli with upstream RPC"
|
|
|
|
case Constants.networkGoerli: return qsTrId("goerli-with-upstream-rpc")
|
|
|
|
//% "Rinkeby with upstream RPC"
|
|
|
|
case Constants.networkRinkeby: return qsTrId("rinkeby-with-upstream-rpc")
|
|
|
|
//% "Ropsten with upstream RPC"
|
|
|
|
case Constants.networkRopsten: return qsTrId("ropsten-with-upstream-rpc")
|
2020-11-23 20:41:57 +00:00
|
|
|
default: return network
|
|
|
|
}
|
|
|
|
}
|
2020-12-03 22:26:05 +00:00
|
|
|
|
2020-12-04 14:53:00 +00:00
|
|
|
function validatePasswords(item, firstPasswordField, repeatPasswordField) {
|
2020-12-03 22:26:05 +00:00
|
|
|
switch (item) {
|
|
|
|
case "first":
|
|
|
|
if (firstPasswordField.text === "") {
|
|
|
|
//% "You need to enter a password"
|
|
|
|
return [false, qsTrId("you-need-to-enter-a-password")];
|
|
|
|
} else if (firstPasswordField.text.length < 6) {
|
|
|
|
return [false, qsTrId("Password needs to be 6 characters or more")];
|
|
|
|
}
|
|
|
|
return [true, ""];
|
|
|
|
|
|
|
|
case "repeat":
|
|
|
|
if (repeatPasswordField.text === "") {
|
|
|
|
//% "You need to repeat your password"
|
|
|
|
return [false, qsTrId("you-need-to-repeat-your-password")];
|
|
|
|
} else if (repeatPasswordField.text !== firstPasswordField.text) {
|
2021-02-18 16:36:05 +00:00
|
|
|
//% "Passwords don't match"
|
|
|
|
return [false, qsTrId("passwords-don-t-match")];
|
2020-12-03 22:26:05 +00:00
|
|
|
}
|
|
|
|
return [true, ""];
|
|
|
|
|
|
|
|
default:
|
|
|
|
return [false, ""];
|
|
|
|
}
|
|
|
|
}
|
feat: whitelist gifs (no url extension needed)
Fixes #1377.
Fixes #1479.
Two sites have been added to the whitelist: giphy.com and tenor.com.
`imageUrls` in its entirety has been removed and instead all links are being handle through the message `linkUrls`. This prevents double-handling of urls that may or may not be images.
The logic to automatically show links previews works like this:
1. If the setting "display chat images" is enabled, all links that *contain* ".png", ".jpg", ".jpeg", ".svg", ".gif" will be automatically shown. If the URL doesn't contain the extension, we are not downloading it. This was meant to be somewhat of a security compromise as we do not want to download each and every link posted in a message just to find out its true content type.
2. If the above setting is *disabled*, then we follow the whitelist settings for tenor and giphy. This allows us to preview gifs that do not have a file extension in their url.
feat: bump status-go to the commit that supports the new whitelist (https://github.com/status-im/status-go/pull/2094), and also lets us get link preview data from urls in the whitelist. NOTE: this commit was branched off status-go `develop`, so once it is merged, and we update this PR to the new commit, we will effectively be getting status-go develop changes. We *could* base that status-go PR off of master if it makes things easier.
fix: height on settings update issue
feat: move date/time of message below links
fix: layout issues when changing setting `neverAskAboutUnfurlingAgain`
feat: Add MessageBorder component to aid in showing rounded corners with different radius
2020-12-11 00:53:44 +00:00
|
|
|
|
|
|
|
function getHostname(url) {
|
|
|
|
const rgx = /\:\/\/(?:[a-zA-Z0-9\-]*\.{1,}){1,}[a-zA-Z0-9]*/i
|
|
|
|
const matches = rgx.exec(url)
|
2021-02-25 19:32:39 +00:00
|
|
|
if (!matches || !matches.length) {
|
|
|
|
if (url.includes(Constants.deepLinkPrefix)) {
|
|
|
|
return Constants.deepLinkPrefix
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
feat: whitelist gifs (no url extension needed)
Fixes #1377.
Fixes #1479.
Two sites have been added to the whitelist: giphy.com and tenor.com.
`imageUrls` in its entirety has been removed and instead all links are being handle through the message `linkUrls`. This prevents double-handling of urls that may or may not be images.
The logic to automatically show links previews works like this:
1. If the setting "display chat images" is enabled, all links that *contain* ".png", ".jpg", ".jpeg", ".svg", ".gif" will be automatically shown. If the URL doesn't contain the extension, we are not downloading it. This was meant to be somewhat of a security compromise as we do not want to download each and every link posted in a message just to find out its true content type.
2. If the above setting is *disabled*, then we follow the whitelist settings for tenor and giphy. This allows us to preview gifs that do not have a file extension in their url.
feat: bump status-go to the commit that supports the new whitelist (https://github.com/status-im/status-go/pull/2094), and also lets us get link preview data from urls in the whitelist. NOTE: this commit was branched off status-go `develop`, so once it is merged, and we update this PR to the new commit, we will effectively be getting status-go develop changes. We *could* base that status-go PR off of master if it makes things easier.
fix: height on settings update issue
feat: move date/time of message below links
fix: layout issues when changing setting `neverAskAboutUnfurlingAgain`
feat: Add MessageBorder component to aid in showing rounded corners with different radius
2020-12-11 00:53:44 +00:00
|
|
|
return matches[0].substring(3)
|
|
|
|
}
|
|
|
|
|
|
|
|
function hasImageExtension(url) {
|
2021-03-10 04:59:01 +00:00
|
|
|
return Constants.acceptedImageExtensions.some(ext => url.includes(ext))
|
|
|
|
}
|
|
|
|
|
|
|
|
function hasDragNDropImageExtension(url) {
|
|
|
|
return Constants.acceptedDragNDropImageExtensions.some(ext => url.includes(ext))
|
|
|
|
}
|
|
|
|
|
|
|
|
function deduplicate(array) {
|
|
|
|
return Array.from(new Set(array))
|
feat: whitelist gifs (no url extension needed)
Fixes #1377.
Fixes #1479.
Two sites have been added to the whitelist: giphy.com and tenor.com.
`imageUrls` in its entirety has been removed and instead all links are being handle through the message `linkUrls`. This prevents double-handling of urls that may or may not be images.
The logic to automatically show links previews works like this:
1. If the setting "display chat images" is enabled, all links that *contain* ".png", ".jpg", ".jpeg", ".svg", ".gif" will be automatically shown. If the URL doesn't contain the extension, we are not downloading it. This was meant to be somewhat of a security compromise as we do not want to download each and every link posted in a message just to find out its true content type.
2. If the above setting is *disabled*, then we follow the whitelist settings for tenor and giphy. This allows us to preview gifs that do not have a file extension in their url.
feat: bump status-go to the commit that supports the new whitelist (https://github.com/status-im/status-go/pull/2094), and also lets us get link preview data from urls in the whitelist. NOTE: this commit was branched off status-go `develop`, so once it is merged, and we update this PR to the new commit, we will effectively be getting status-go develop changes. We *could* base that status-go PR off of master if it makes things easier.
fix: height on settings update issue
feat: move date/time of message below links
fix: layout issues when changing setting `neverAskAboutUnfurlingAgain`
feat: Add MessageBorder component to aid in showing rounded corners with different radius
2020-12-11 00:53:44 +00:00
|
|
|
}
|
2021-04-12 15:40:49 +00:00
|
|
|
|
|
|
|
// Leave this function at the bottom of the file as QT Creator messes up the code color after this
|
|
|
|
function isPunct(c) {
|
|
|
|
return /(!|\@|#|\$|%|\^|&|\*|\(|\)|_|\+|\||-|=|\\|{|}|[|]|"|;|'|<|>|\?|,|\.|\/)/.test(c)
|
|
|
|
}
|
2020-06-22 15:51:15 +00:00
|
|
|
}
|