Files: 7f4a4d5b90c62d06c0bfcd39e29051e47d4f4fef / lib / depject / profile / html / preview.js
4922 bytesRaw
1 | const nest = require('depnest') |
2 | const h = require('mutant/h') |
3 | const map = require('mutant/map') |
4 | const when = require('mutant/when') |
5 | const computed = require('mutant/computed') |
6 | const send = require('mutant/send') |
7 | const removeMd = require('remove-markdown') |
8 | |
9 | exports.needs = nest({ |
10 | 'about.obs.name': 'first', |
11 | 'about.obs.description': 'first', |
12 | 'about.html.image': 'first', |
13 | 'keys.sync.id': 'first', |
14 | 'sheet.display': 'first', |
15 | 'app.navigate': 'first', |
16 | 'intl.sync.i18n': 'first', |
17 | 'intl.sync.i18n_n': 'first', |
18 | 'sheet.profiles': 'first', |
19 | 'contact.html.followToggle': 'first', |
20 | 'profile.obs.contact': 'first' |
21 | }) |
22 | |
23 | exports.gives = nest('profile.html.preview') |
24 | |
25 | exports.create = function (api) { |
26 | const i18n = api.intl.sync.i18n |
27 | const plural = api.intl.sync.i18n_n |
28 | |
29 | return nest('profile.html.preview', function (id) { |
30 | const idLen = id.length |
31 | const name = api.about.obs.name(id) |
32 | const contact = api.profile.obs.contact(id) |
33 | const description = api.about.obs.description(id) |
34 | |
35 | return h('ProfilePreview', [ |
36 | h('header', [ |
37 | h('div.image', api.about.html.image(id)), |
38 | h('div.main', [ |
39 | h('div.title', [ |
40 | h('h1', [ |
41 | h('a', { href: '#', 'ev-click': () => api.app.navigate(id) }, [name]) |
42 | ]), |
43 | h('div.meta', [ |
44 | api.contact.html.followToggle(id, { block: false }) |
45 | ]) |
46 | ]), |
47 | h('section -publicKey', [ |
48 | h('pre', { title: i18n('Public key for this profile') }, id) |
49 | ]), |
50 | h( |
51 | 'section -profile', [ |
52 | computed(description, (description) => { |
53 | const txt = removeMd(description) |
54 | const summary = shortenDescription(txt, idLen) |
55 | return summary |
56 | })] |
57 | ) |
58 | ]) |
59 | ]), |
60 | |
61 | when(contact.isYou, h('section -you', [ |
62 | i18n('This is you.') |
63 | ])), |
64 | |
65 | when(contact.notFollowing, [ |
66 | when(contact.blockingFriendsCount, |
67 | h('section -blockWarning', [ |
68 | h('a', { |
69 | href: '#', |
70 | 'ev-click': send(displayBlockingFriends, contact.blockingFriends) |
71 | }, [ |
72 | '⚠️ ', computed(['This person is blocked by %s of your friends.', contact.blockingFriendsCount], plural) |
73 | ]) |
74 | ]), |
75 | when(contact.noOutgoing, |
76 | h('section -distanceWarning', [ |
77 | '⚠️ ', i18n('This person does not follow anyone that follows you') |
78 | ]), |
79 | when(contact.noIncoming, |
80 | h('section -distanceWarning', [ |
81 | '⚠️ ', i18n('You don\'t follow anyone who follows this person') |
82 | ]), |
83 | when(contact.mutualFriendsCount, |
84 | h('section -mutualFriends', [ |
85 | h('a', { |
86 | href: '#', |
87 | title: nameList(i18n('Mutual Friends'), contact.mutualFriends), |
88 | 'ev-click': send(displayMutualFriends, contact.mutualFriends) |
89 | }, [ |
90 | '👥 ', computed(['You share %s mutual friends with this person.', contact.mutualFriendsCount], plural) |
91 | ]) |
92 | ]), |
93 | h('section -mutualFriends', [ |
94 | h('a', { |
95 | href: '#', |
96 | title: nameList(i18n('Followed by'), contact.incomingVia), |
97 | 'ev-click': send(displayFollowedBy, contact.incomingVia) |
98 | }, [ |
99 | '👥 ', computed(['You follow %s people that follow this person.', contact.incomingViaCount], plural) |
100 | ]) |
101 | ]) |
102 | ) |
103 | ) |
104 | ) |
105 | ) |
106 | ]) |
107 | ]) |
108 | }) |
109 | |
110 | function shortenDescription (txt, len) { |
111 | if (txt == null) { |
112 | return '' |
113 | } |
114 | const line1 = txt.trim().split('\n', 1)[0] |
115 | if (line1.length <= len) { |
116 | return line1 |
117 | } |
118 | const words = line1.split(' ') |
119 | let result = words.shift() |
120 | if (result.length > len) { |
121 | return result.splice(0, len - 1) + ' …' |
122 | } |
123 | for (let i = 0; i < len; i++) { |
124 | const currentWord = words.shift() |
125 | // + 1 for the joining space, and +2 for the final ellipsis |
126 | if (result.length + 1 + currentWord.length + 2 <= len) { |
127 | result += ` ${currentWord}` |
128 | } else { |
129 | break |
130 | } |
131 | } |
132 | return result + ' …' |
133 | } |
134 | |
135 | function displayMutualFriends (profiles) { |
136 | api.sheet.profiles(profiles, i18n('Mutual Friends')) |
137 | } |
138 | |
139 | function displayFollowedBy (profiles) { |
140 | api.sheet.profiles(profiles, i18n('Followed by')) |
141 | } |
142 | |
143 | function displayBlockingFriends (profiles) { |
144 | api.sheet.profiles(profiles, i18n('Blocked by')) |
145 | } |
146 | |
147 | function nameList (prefix, ids) { |
148 | const items = map(ids, api.about.obs.name) |
149 | return computed([prefix, items], (prefix, names) => { |
150 | return (prefix ? (prefix + '\n') : '') + names.map((n) => `- ${n}`).join('\n') |
151 | }) |
152 | } |
153 | } |
154 |
Built with git-ssb-web