diff options
| author | s-ol <s+removethis@s-ol.nu> | 2021-01-25 23:14:26 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2021-01-26 10:21:47 +0000 |
| commit | 9ec0f8e7dfe7ec5b0a55a0ba51eeb986d54d5e9d (patch) | |
| tree | 3ae404d7a404310486352330b57c5437a2b8de56 | |
| parent | styling (diff) | |
| download | fedidag-9ec0f8e7dfe7ec5b0a55a0ba51eeb986d54d5e9d.tar.gz fedidag-9ec0f8e7dfe7ec5b0a55a0ba51eeb986d54d5e9d.zip | |
add avatars
| -rw-r--r-- | package.json | 17 | ||||
| -rw-r--r-- | src/dom.js | 48 | ||||
| -rw-r--r-- | src/index.js | 86 | ||||
| -rw-r--r-- | src/ui.js | 89 | ||||
| -rw-r--r-- | yarn.lock | 90 |
5 files changed, 172 insertions, 158 deletions
diff --git a/package.json b/package.json index fa84d90..a99b5ce 100644 --- a/package.json +++ b/package.json @@ -8,27 +8,32 @@ }, "babel": { "presets": [ - "@babel/env", - "@babel/react" + "@babel/env" ], "plugins": [ - "@babel/plugin-proposal-class-properties" + "@babel/plugin-proposal-class-properties", + [ + "@babel/plugin-transform-react-jsx", + { + "pragma": "dom.createElement", + "pragmaFrag": "dom.createFragment" + } + ] ] }, "dependencies": { "color-hash": "^1.0.3", "core-js": "^3.8.3", "dagre": "^0.8.5", + "date-fns": "^2.16.1", "jsonld": "^3.3.0", - "react": "^16.2.0", - "react-dom": "^16.2.0", "regenerator-runtime": "^0.13.7" }, "devDependencies": { "@babel/core": "^7.11.6", "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-transform-react-jsx": "^7.12.12", "@babel/preset-env": "^7.11.5", - "@babel/preset-react": "^7.10.4", "babel-loader": "^8.2.2", "html-webpack-plugin": "^4.5.0", "webpack": "^4.20.2", diff --git a/src/dom.js b/src/dom.js new file mode 100644 index 0000000..9e44d0a --- /dev/null +++ b/src/dom.js @@ -0,0 +1,48 @@ +export const css = ([ code] ) => { + const style = document.createElement('style'); + document.head.appendChild(style); + style.appendChild(document.createTextNode('')); + + let i = 0; + for (const v of code.split('}')) { + if (v.indexOf('{') < 0) continue; + style.sheet.insertRule(v + '}', i++); + } + + return style; +}; + +const appendChild = (parent, child) => { + if (Array.isArray(child)) { + child.forEach((nestedChild) => appendChild(parent, nestedChild)); + } else { + parent.appendChild(child.nodeType ? child : document.createTextNode(child)); + } +} + +const objectProps = { style: true, dataset: true }; + +export const createElement = (tag, props, ...children) => { + if ('function' === typeof tag) + return tag(props, children); + + const element = document.createElement(tag); + + for (const [name, value] of Object.entries(props || {})) { + if (name.startsWith('on') && name.toLowerCase() in window) { + element.addEventListener(name.toLowerCase().substr(2), value); + } else if (objectProps[name]) { + Object.assign(element[name], value); + } else { + element.setAttribute(name, value.toString()); + } + } + + for (const child of children) { + appendChild(element, child); + } + + return element; +} + +export const createFragment = (props, ...children) => children; diff --git a/src/index.js b/src/index.js index 254821a..187464b 100644 --- a/src/index.js +++ b/src/index.js @@ -2,49 +2,15 @@ import 'core-js/stable'; import 'regenerator-runtime/runtime'; import * as jsonld from 'jsonld'; import dagre from 'dagre'; -import ColorHash from 'color-hash'; +import * as dom from './dom'; +import { Note } from './ui'; -const css = ([ code] ) => { - const style = document.createElement('style'); - document.head.appendChild(style); - style.appendChild(document.createTextNode('')); - - let i = 0; - for (const v of code.split('}')) { - if (v.indexOf('{') < 0) continue; - style.sheet.insertRule(v + '}', i++); - } - - return style; -}; - -css` +dom.css` article { position: relative; } - -section { - position: absolute; - overflow: hidden; - - width: 350px; - - background: #696969; - border-radius: 8px; -} - -section > header { - padding: 0.75em 1em 0.5em; - color: #121212; -} - -section > main { - padding: 1em; - color: #eeeeee; -} `; -const colors = new ColorHash({ lightness: 0.8 }); const context = 'https://www.w3.org/ns/activitystreams'; const userCache = {}; @@ -54,6 +20,7 @@ const loadUser = async (id) => { const result = await jsonld.compact(id, context); userCache[id] = result; + result.icon.url = new URL(result.icon.url, id).href; return result; } @@ -71,31 +38,6 @@ const loadData = async () => { const article = document.createElement('article'); document.body.appendChild(article); -const createNode = (data) => { - const root = document.createElement('section'); - root.dataset.dagId = data.id; - - const header = document.createElement('header'); - header.style.backgroundColor = data.attributedTo.color || colors.hex(data.attributedTo.id); - const author = document.createElement('span'); - author.textContent = data.attributedTo.name || data.attributedTo.preferredUsername; - header.appendChild(author); - root.appendChild(header); - - const main = document.createElement('main'); - main.innerHTML = data.content; - root.appendChild(main); - - article.appendChild(root); - - return { - data, - root, - width: root.offsetWidth, - height: root.offsetHeight, - }; -}; - loadData().then(data => { window.dagData = data; const graph = new dagre.graphlib.Graph(); @@ -107,14 +49,20 @@ loadData().then(data => { graph.setGraph({}); graph.setDefaultEdgeLabel(() => ({})); - let rootNode; + let rootId; for (const data of data['@graph']) { - const node = createNode(data); - graph.setNode(data.id, node); + const dom = <Note {...data} />; + article.appendChild(dom); + + graph.setNode(data.id, { + dom, data, + width: dom.offsetWidth, + height: dom.offsetHeight, + }); if (!data.inReplyTo || !data.inReplyTo.length) - rootNode = node; + rootId = data.id; if (data.replies && !Array.isArray(data.replies)) data.replies = [ data.replies ]; @@ -124,7 +72,6 @@ loadData().then(data => { } } - console.log(rootNode); dagre.layout(graph); const info = graph.graph(); @@ -133,8 +80,8 @@ loadData().then(data => { for (const id of graph.nodes()) { const node = graph.node(id); - node.root.style.left = `${node.x - node.width / 2}px`; - node.root.style.top = `${node.y - node.height / 2}px`; + node.dom.style.left = `${node.x - node.width / 2}px`; + node.dom.style.top = `${node.y - node.height / 2}px`; } const ctx = canvas.getContext('2d'); @@ -153,5 +100,6 @@ loadData().then(data => { ctx.stroke(); } + const rootNode = graph.node(rootId); window.scrollTo(rootNode.x - window.innerWidth/2, rootNode.y); }); diff --git a/src/ui.js b/src/ui.js new file mode 100644 index 0000000..10755e6 --- /dev/null +++ b/src/ui.js @@ -0,0 +1,89 @@ +import ColorHash from 'color-hash'; +import { formatRelative } from 'date-fns'; +import * as dom from './dom'; + +dom.css` +body { + background: #1e1e1e; + font-family: sans-serif; +} +`; + +const now = new Date(); +const Time = ({ time }) => { + const dt = new Date(time); + return formatRelative(dt, now); +}; + +dom.css` +.flex-space { + flex: 1; +} +`; + +const Space = () => <div class="flex-space" />; + +dom.css` +section { + position: absolute; + overflow: hidden; + + width: 350px; + + background: #363636; + border-radius: 0.4em; +} + +section > header { + display: flex; + flex-direction: row; + + height: 2.5em; + line-height: 2.5em; + + color: #121212; +} + +section > header > * { + margin: 0 0.5em; +} + +section > header > img { + height: 2em; + width: 2em; + margin: 0.25em; + border-radius: 0.2em; +} + +section > header > .time { + font-size: 0.8em; + color: #363636; +} + +section > main { + padding: 1em; + color: #eeeeee; + font-family: serif; +} +`; + +const colors = new ColorHash({ lightness: 0.8 }); +export const Note = ({ id, attributedTo, published, content }) => { + const backgroundColor = attributedTo.color || colors.hex(attributedTo.id); + const username = attributedTo.name || attributedTo.preferredUsername; + + return ( + <section dataset={{ id }}> + <header style={{ backgroundColor }}> + <img src={attributedTo.icon.url} /> + <span class="user">{username}</span> + <Space /> + <span class="time"><Time time={published} /></span> + </header> + <main> + {content} + </main> + </section> + ); +}; + @@ -633,21 +633,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-display-name@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" - integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-react-jsx-development@^7.12.7": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" - integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.12.12" - -"@babel/plugin-transform-react-jsx@^7.12.10", "@babel/plugin-transform-react-jsx@^7.12.12": +"@babel/plugin-transform-react-jsx@^7.12.12": version "7.12.12" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e" integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw== @@ -658,14 +644,6 @@ "@babel/plugin-syntax-jsx" "^7.12.1" "@babel/types" "^7.12.12" -"@babel/plugin-transform-react-pure-annotations@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" - integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-regenerator@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" @@ -814,17 +792,6 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.10.4": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" - integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-react-display-name" "^7.12.1" - "@babel/plugin-transform-react-jsx" "^7.12.10" - "@babel/plugin-transform-react-jsx-development" "^7.12.7" - "@babel/plugin-transform-react-pure-annotations" "^7.12.1" - "@babel/runtime@^7.8.4": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" @@ -1981,6 +1948,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.16.1.tgz#05775792c3f3331da812af253e1a935851d3834b" + integrity sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3366,7 +3338,7 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -3516,13 +3488,6 @@ loglevel@^1.6.8: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== -loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - lower-case@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" @@ -4217,15 +4182,6 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= -prop-types@^15.6.2: - version "15.7.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" - integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.8.1" - proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -4359,30 +4315,6 @@ rdf-canonize@^2.0.1: semver "^6.3.0" setimmediate "^1.0.5" -react-dom@^16.2.0: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" - integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.1" - -react-is@^16.8.1: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react@^16.2.0: - version "16.14.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" - integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - prop-types "^15.6.2" - "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -4636,14 +4568,6 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -scheduler@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" - integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" |
