Files: ee234ad644780313d6a36bed781c9df63d190563 / modules / app / link-preview.js
3002 bytesRaw
1 | var { h, Value, computed } = require('mutant') |
2 | var ObserveLinkHover = require('../../lib/observe-link-hover') |
3 | var ref = require('ssb-ref') |
4 | |
5 | var nest = require('depnest') |
6 | |
7 | exports.needs = nest({ |
8 | 'intl.sync.i18n': 'first', |
9 | 'profile.html.preview': 'first', |
10 | 'channel.html.preview': 'first' |
11 | }) |
12 | |
13 | exports.gives = nest('app.linkPreview') |
14 | |
15 | exports.create = function (api) { |
16 | var i18n = api.intl.sync.i18n |
17 | return nest('app.linkPreview', function (container, delay) { |
18 | var currentHover = ObserveLinkHover(container, (value, lastValue) => { |
19 | var href = value && value.getAttribute('href') |
20 | var oldHref = lastValue && lastValue.getAttribute('href') |
21 | |
22 | var delay = 500 |
23 | if (href && oldHref) { |
24 | delay = 100 |
25 | } else if (!value) { |
26 | delay = 200 |
27 | } |
28 | |
29 | return delay |
30 | }) |
31 | var previewElement = Value() |
32 | |
33 | // hide preview on scroll |
34 | var hasPreview = computed(previewElement, x => !!x) |
35 | hasPreview(value => { |
36 | if (value) { |
37 | window.addEventListener('wheel', previewElement.cancel) |
38 | } else { |
39 | window.removeEventListener('wheel', previewElement.cancel) |
40 | } |
41 | }) |
42 | |
43 | currentHover(element => { |
44 | var href = element && element.getAttribute('href') |
45 | var preview = null |
46 | |
47 | if (href) { |
48 | if (ref.isFeed(href)) { |
49 | preview = api.profile.html.preview(href) |
50 | } else if (href.includes('://')) { |
51 | preview = h('ProfilePreview', [ |
52 | h('section', [ |
53 | h('strong', [i18n('External Link'), ' ๐']), h('br'), |
54 | h('code', href) |
55 | ]) |
56 | ]) |
57 | } else if (href.startsWith('#') && href.length > 1) { |
58 | preview = api.channel.html.preview(href.slice(1)) |
59 | } |
60 | } |
61 | |
62 | if (preview) { |
63 | var rect = element.getBoundingClientRect() |
64 | var width = 510 |
65 | var maxLeft = window.innerWidth - width |
66 | var maxTop = window.innerHeight - 100 |
67 | var distanceFromRight = window.innerWidth - rect.right |
68 | var shouldDisplayBeside = rect.bottom > maxTop || rect.left < 50 || distanceFromRight < 50 |
69 | |
70 | if (shouldDisplayBeside && rect.bottom > 50) { |
71 | if (rect.right > maxLeft && (rect.left - width) < 0) { |
72 | // no room, just give up! |
73 | previewElement.set(null) |
74 | return |
75 | } else { |
76 | preview.style.top = `${Math.min(rect.top, maxTop)}px` |
77 | if (rect.right > maxLeft) { |
78 | preview.style.left = `${rect.left - width}px` |
79 | } else { |
80 | preview.style.left = `${rect.right + 5}px` |
81 | } |
82 | } |
83 | } else { |
84 | preview.style.top = `${rect.bottom + 5}px` |
85 | preview.style.left = `${Math.min(rect.left, maxLeft)}px` |
86 | } |
87 | |
88 | previewElement.set(preview) |
89 | } else if (element !== false) { |
90 | previewElement.set(null) |
91 | } |
92 | }) |
93 | |
94 | previewElement.cancel = function () { |
95 | currentHover.cancel() |
96 | previewElement.set(null) |
97 | } |
98 | |
99 | return previewElement |
100 | }) |
101 | } |
102 |
Built with git-ssb-web