interface: convert lib/util to TS

This commit is contained in:
Liam Fitzgerald 2020-10-27 15:32:56 +10:00
parent 1d65e52351
commit d89ccffb62
2 changed files with 309 additions and 254 deletions

View File

@ -1,254 +0,0 @@
import _ from 'lodash';
import f from 'lodash/fp';
export const MOBILE_BROWSER_REGEX = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i;
export function clamp(x,min,max) {
return Math.max(min, Math.min(max, x));
}
// color is a #000000 color
export function adjustHex(color, amount) {
const res = f.flow(
f.split(''), f.chunk(2), // get individual color channels
f.map(c => parseInt(c.join(''), 16)), // as hex
f.map(c => clamp(c + amount, 0, 255).toString(16)), // adjust
f.join('')
)(color.slice(1))
return `#${res}`;
}
export function resourceAsPath(resource) {
const { name, ship } = resource;
return `/ship/~${ship}/${name}`;
}
export function uuid() {
let str = '0v';
str += Math.ceil(Math.random()*8)+'.';
for (let i = 0; i < 5; i++) {
let _str = Math.ceil(Math.random()*10000000).toString(32);
_str = ('00000'+_str).substr(-5,5);
str += _str+'.';
}
return str.slice(0,-1);
}
/*
Goes from:
~2018.7.17..23.15.09..5be5 // urbit @da
To:
(javascript Date object)
*/
export function daToDate(st) {
const dub = function(n) {
return parseInt(n) < 10 ? '0' + parseInt(n) : n.toString();
};
const da = st.split('..');
const bigEnd = da[0].split('.');
const lilEnd = da[1].split('.');
const ds = `${bigEnd[0].slice(1)}-${dub(bigEnd[1])}-${dub(bigEnd[2])}T${dub(lilEnd[0])}:${dub(lilEnd[1])}:${dub(lilEnd[2])}Z`;
return new Date(ds);
}
/*
Goes from:
(javascript Date object)
To:
~2018.7.17..23.15.09..5be5 // urbit @da
*/
export function dateToDa(d, mil) {
  const fil = function(n) {
    return n >= 10 ? n : '0' + n;
  };
  return (
    `~${d.getUTCFullYear()}.` +
    `${(d.getUTCMonth() + 1)}.` +
    `${fil(d.getUTCDate())}..` +
    `${fil(d.getUTCHours())}.` +
    `${fil(d.getUTCMinutes())}.` +
    `${fil(d.getUTCSeconds())}` +
`${mil ? '..0000' : ''}`
  );
}
export function deSig(ship) {
if(!ship) {
return null;
}
return ship.replace('~', '');
}
export function uxToHex(ux) {
if (ux.length > 2 && ux.substr(0,2) === '0x') {
const value = ux.substr(2).replace('.', '').padStart(6, '0');
return value;
}
const value = ux.replace('.', '').padStart(6, '0');
return value;
}
export function hexToUx(hex) {
const ux = f.flow(
f.chunk(4),
f.map(x => _.dropWhile(x, y => y === 0).join('')),
f.join('.')
)(hex.split(''))
return `0x${ux}`;
}
export function writeText(str) {
return new Promise(((resolve, reject) => {
const range = document.createRange();
range.selectNodeContents(document.body);
document.getSelection().addRange(range);
let success = false;
function listener(e) {
e.clipboardData.setData('text/plain', str);
e.preventDefault();
success = true;
}
document.addEventListener('copy', listener);
document.execCommand('copy');
document.removeEventListener('copy', listener);
document.getSelection().removeAllRanges();
success ? resolve() : reject();
})).catch((error) => {
console.error(error);
});;
};
// trim patps to match dojo, chat-cli
export function cite(ship) {
let patp = ship, shortened = '';
if (patp === null || patp === '') {
return null;
}
if (patp.startsWith('~')) {
patp = patp.substr(1);
}
// comet
if (patp.length === 56) {
shortened = '~' + patp.slice(0, 6) + '_' + patp.slice(50, 56);
return shortened;
}
// moon
if (patp.length === 27) {
shortened = '~' + patp.slice(14, 20) + '^' + patp.slice(21, 27);
return shortened;
}
return `~${patp}`;
}
export function alphabeticalOrder(a,b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
}
// TODO: deprecated
export function alphabetiseAssociations(associations) {
const result = {};
Object.keys(associations).sort((a, b) => {
let aName = a.substr(1);
let bName = b.substr(1);
if (associations[a].metadata && associations[a].metadata.title) {
aName = associations[a].metadata.title !== ''
? associations[a].metadata.title
: a.substr(1);
}
if (associations[b].metadata && associations[b].metadata.title) {
bName = associations[b].metadata.title !== ''
? associations[b].metadata.title
: b.substr(1);
}
return alphabeticalOrder(aName,bName);
}).map((each) => {
result[each] = associations[each];
});
return result;
}
// encode the string into @ta-safe format, using logic from +wood.
// for example, 'some Chars!' becomes '~.some.~43.hars~21.'
//
export function stringToTa(string) {
let out = '';
for (let i = 0; i < string.length; i++) {
const char = string[i];
let add = '';
switch (char) {
case ' ':
add = '.';
break;
case '.':
add = '~.';
break;
case '~':
add = '~~';
break;
default:
const charCode = string.charCodeAt(i);
if (
(charCode >= 97 && charCode <= 122) || // a-z
(charCode >= 48 && charCode <= 57) || // 0-9
char === '-'
) {
add = char;
} else {
// TODO behavior for unicode doesn't match +wood's,
// but we can probably get away with that for now.
add = '~' + charCode.toString(16) + '.';
}
}
out = out + add;
}
return '~.' + out;
}
export function amOwnerOfGroup(groupPath) {
if (!groupPath)
return false;
const groupOwner = /(\/~)?\/~([a-z-]{3,})\/.*/.exec(groupPath)[2];
return window.ship === groupOwner;
}
export function getContactDetails(contact) {
const member = !contact;
contact = contact || {
nickname: '',
avatar: null,
color: '0x0'
};
const nickname = contact.nickname || '';
const color = uxToHex(contact.color || '0x0');
const avatar = contact.avatar || null;
return { nickname, color, member, avatar };
}
export function stringToSymbol(str) {
let result = '';
for (let i = 0; i < str.length; i++) {
const n = str.charCodeAt(i);
if (((n >= 97) && (n <= 122)) ||
((n >= 48) && (n <= 57))) {
result += str[i];
} else if ((n >= 65) && (n <= 90)) {
result += String.fromCharCode(n + 32);
} else {
result += '-';
}
}
result = result.replace(/^[\-\d]+|\-+/g, '-');
result = result.replace(/^\-+|\-+$/g, '');
if (result === '') {
return dateToDa(new Date());
}
return result;
}

View File

@ -0,0 +1,309 @@
import _ from "lodash";
import f from "lodash/fp";
import bigInt, { BigInteger } from "big-integer";
export const MOBILE_BROWSER_REGEX = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i;
export const MOMENT_CALENDAR_DATE = {
sameDay: "[Today]",
nextDay: "[Tomorrow]",
nextWeek: "dddd",
lastDay: "[Yesterday]",
lastWeek: "[Last] dddd",
sameElse: "DD/MM/YYYY",
};
const DA_UNIX_EPOCH = bigInt("170141184475152167957503069145530368000"); // `@ud` ~1970.1.1
const DA_SECOND = bigInt("18446744073709551616"); // `@ud` ~s1
export function daToUnix(da: BigInteger) {
// ported from +time:enjs:format in hoon.hoon
const offset = DA_SECOND.divide(bigInt(2000));
const epochAdjusted = offset.add(da.subtract(DA_UNIX_EPOCH));
return Math.round(
epochAdjusted.multiply(bigInt(1000)).divide(DA_SECOND).toJSNumber()
);
}
export function makePatDa(patda: string) {
return bigInt(udToDec(patda));
}
export function udToDec(ud: string): string {
return ud.replace(/\./g, "");
}
export function decToUd(str: string): string {
return _.trimStart(
f.flow(
f.split(""),
f.reverse,
f.chunk(3),
f.map(f.flow(f.reverse, f.join(""))),
f.reverse,
f.join(".")
)(str),
"0."
);
}
/**
* Clamp a number between a min and max
*/
export function clamp(x: number, min: number, max: number) {
return Math.max(min, Math.min(max, x));
}
// color is a #000000 color
export function adjustHex(color: string, amount: number): string {
return f.flow(
f.split(""),
f.chunk(2), // get RGB channels
f.map((c) => parseInt(c.join(""), 16)), // as hex
f.map((c) => clamp(c + amount, 0, 255).toString(16)), // adjust
f.join(""),
(res) => `#${res}` //format
)(color.slice(1));
}
export function resourceAsPath(resource: any) {
const { name, ship } = resource;
return `/ship/~${ship}/${name}`;
}
export function uuid() {
let str = "0v";
str += Math.ceil(Math.random() * 8) + ".";
for (let i = 0; i < 5; i++) {
let _str = Math.ceil(Math.random() * 10000000).toString(32);
_str = ("00000" + _str).substr(-5, 5);
str += _str + ".";
}
return str.slice(0, -1);
}
/*
Goes from:
~2018.7.17..23.15.09..5be5 // urbit @da
To:
(javascript Date object)
*/
export function daToDate(st: string) {
const dub = function (n: string) {
return parseInt(n) < 10 ? "0" + parseInt(n) : n.toString();
};
const da = st.split("..");
const bigEnd = da[0].split(".");
const lilEnd = da[1].split(".");
const ds = `${bigEnd[0].slice(1)}-${dub(bigEnd[1])}-${dub(bigEnd[2])}T${dub(
lilEnd[0]
)}:${dub(lilEnd[1])}:${dub(lilEnd[2])}Z`;
return new Date(ds);
}
/*
Goes from:
(javascript Date object)
To:
~2018.7.17..23.15.09..5be5 // urbit @da
*/
export function dateToDa(d: Date, mil: boolean = false) {
const fil = function (n: number) {
return n >= 10 ? n : "0" + n;
};
return (
`~${d.getUTCFullYear()}.` +
`${d.getUTCMonth() + 1}.` +
`${fil(d.getUTCDate())}..` +
`${fil(d.getUTCHours())}.` +
`${fil(d.getUTCMinutes())}.` +
`${fil(d.getUTCSeconds())}` +
`${mil ? "..0000" : ""}`
);
}
export function deSig(ship: string) {
if (!ship) {
return null;
}
return ship.replace("~", "");
}
export function uxToHex(ux: string) {
if (ux.length > 2 && ux.substr(0, 2) === "0x") {
const value = ux.substr(2).replace(".", "").padStart(6, "0");
return value;
}
const value = ux.replace(".", "").padStart(6, "0");
return value;
}
export const hexToUx: (hex: string) => string = f.flow(
f.split(""),
f.chunk(4),
f.map(
f.flow(
f.dropWhile((y) => y === 0),
f.join
)
),
f.join("."),
(x) => `0x${x}`
);
export function writeText(str: string) {
return new Promise<void>((resolve, reject) => {
const range = document.createRange();
range.selectNodeContents(document.body);
document?.getSelection()?.addRange(range);
let success = false;
function listener(e) {
e.clipboardData.setData("text/plain", str);
e.preventDefault();
success = true;
}
document.addEventListener("copy", listener);
document.execCommand("copy");
document.removeEventListener("copy", listener);
document?.getSelection()?.removeAllRanges();
success ? resolve() : reject();
}).catch((error) => {
console.error(error);
});
}
// trim patps to match dojo, chat-cli
export function cite(ship: string) {
let patp = ship,
shortened = "";
if (patp === null || patp === "") {
return null;
}
if (patp.startsWith("~")) {
patp = patp.substr(1);
}
// comet
if (patp.length === 56) {
shortened = "~" + patp.slice(0, 6) + "_" + patp.slice(50, 56);
return shortened;
}
// moon
if (patp.length === 27) {
shortened = "~" + patp.slice(14, 20) + "^" + patp.slice(21, 27);
return shortened;
}
return `~${patp}`;
}
export function alphabeticalOrder(a: string, b: string) {
return a.toLowerCase().localeCompare(b.toLowerCase());
}
// TODO: deprecated
export function alphabetiseAssociations(associations: any) {
const result = {};
Object.keys(associations)
.sort((a, b) => {
let aName = a.substr(1);
let bName = b.substr(1);
if (associations[a].metadata && associations[a].metadata.title) {
aName =
associations[a].metadata.title !== ""
? associations[a].metadata.title
: a.substr(1);
}
if (associations[b].metadata && associations[b].metadata.title) {
bName =
associations[b].metadata.title !== ""
? associations[b].metadata.title
: b.substr(1);
}
return alphabeticalOrder(aName, bName);
})
.map((each) => {
result[each] = associations[each];
});
return result;
}
// encode the string into @ta-safe format, using logic from +wood.
// for example, 'some Chars!' becomes '~.some.~43.hars~21.'
//
export function stringToTa(str: string) {
let out = "";
for (let i = 0; i < str.length; i++) {
const char = str[i];
let add = "";
switch (char) {
case " ":
add = ".";
break;
case ".":
add = "~.";
break;
case "~":
add = "~~";
break;
default:
const charCode = str.charCodeAt(i);
if (
(charCode >= 97 && charCode <= 122) || // a-z
(charCode >= 48 && charCode <= 57) || // 0-9
char === "-"
) {
add = char;
} else {
// TODO behavior for unicode doesn't match +wood's,
// but we can probably get away with that for now.
add = "~" + charCode.toString(16) + ".";
}
}
out = out + add;
}
return "~." + out;
}
export function amOwnerOfGroup(groupPath: string) {
if (!groupPath) return false;
const groupOwner = /(\/~)?\/~([a-z-]{3,})\/.*/.exec(groupPath)?.[2];
return window.ship === groupOwner;
}
export function getContactDetails(contact: any) {
const member = !contact;
contact = contact || {
nickname: "",
avatar: null,
color: "0x0",
};
const nickname = contact.nickname || "";
const color = uxToHex(contact.color || "0x0");
const avatar = contact.avatar || null;
return { nickname, color, member, avatar };
}
export function stringToSymbol(str: string) {
let result = "";
for (let i = 0; i < str.length; i++) {
const n = str.charCodeAt(i);
if ((n >= 97 && n <= 122) || (n >= 48 && n <= 57)) {
result += str[i];
} else if (n >= 65 && n <= 90) {
result += String.fromCharCode(n + 32);
} else {
result += "-";
}
}
result = result.replace(/^[\-\d]+|\-+/g, "-");
result = result.replace(/^\-+|\-+$/g, "");
if (result === "") {
return dateToDa(new Date());
}
return result;
}