Commit 85d9ae042b27a93cc430e3c2ca805da1d89bd739
profile suggest: prioritize thread participants, highlight following
Matt McKegg committed on 2/12/2018, 8:58:56 PMParent: 2a20acf33d2e0b90142c3b19c1a1fa74d59d32da
Files changed
modules/message/html/compose.js | changed |
modules/page/html/render/message.js | changed |
modules/profile/async/suggest.js | changed |
styles/dark/suggest-box.mcss | changed |
styles/light/suggest-box.mcss | changed |
modules/message/html/compose.js | ||
---|---|---|
@@ -23,9 +23,9 @@ | ||
23 | 23 | exports.gives = nest('message.html.compose') |
24 | 24 | |
25 | 25 | exports.create = function (api) { |
26 | 26 | const i18n = api.intl.sync.i18n |
27 | - return nest('message.html.compose', function ({shrink = true, isPrivate, meta, hooks, prepublish, placeholder = 'Write a message'}, cb) { | |
27 | + return nest('message.html.compose', function ({shrink = true, isPrivate, participants, meta, hooks, prepublish, placeholder = 'Write a message'}, cb) { | |
28 | 28 | var files = [] |
29 | 29 | var filesById = {} |
30 | 30 | var focused = Value(false) |
31 | 31 | var hasContent = Value(false) |
@@ -133,9 +133,9 @@ | ||
133 | 133 | } |
134 | 134 | |
135 | 135 | addSuggest(textArea, (inputText, cb) => { |
136 | 136 | if (inputText[0] === '@') { |
137 | - cb(null, getProfileSuggestions(inputText.slice(1))) | |
137 | + cb(null, getProfileSuggestions(inputText.slice(1), resolve(participants))) | |
138 | 138 | } else if (inputText[0] === '#') { |
139 | 139 | cb(null, getChannelSuggestions(inputText.slice(1))) |
140 | 140 | } else if (inputText[0] === ':') { |
141 | 141 | // suggest emojis |
modules/page/html/render/message.js | ||
---|---|---|
@@ -26,8 +26,9 @@ | ||
26 | 26 | var loader = h('div', {className: 'Loading -large'}) |
27 | 27 | |
28 | 28 | var result = Proxy(loader) |
29 | 29 | var anchor = Value() |
30 | + var participants = Proxy([]) | |
30 | 31 | |
31 | 32 | var meta = Struct({ |
32 | 33 | type: 'post', |
33 | 34 | root: Proxy(id), |
@@ -40,8 +41,9 @@ | ||
40 | 41 | var compose = api.message.html.compose({ |
41 | 42 | meta, |
42 | 43 | isPrivate: when(meta.recps, true), |
43 | 44 | shrink: false, |
45 | + participants, | |
44 | 46 | hooks: [ |
45 | 47 | AnchorHook('reply', anchor, (el) => el.focus()) |
46 | 48 | ], |
47 | 49 | placeholder: when(meta.recps, i18n('Write a private reply'), i18n('Write a public reply')) |
@@ -80,8 +82,12 @@ | ||
80 | 82 | |
81 | 83 | // if root thread, reply to last post |
82 | 84 | meta.branch.set(isReply ? thread.branchId : thread.lastId) |
83 | 85 | |
86 | + participants.set(computed(thread.messages, messages => { | |
87 | + return messages.map(msg => msg && msg.value && msg.value.author) | |
88 | + })) | |
89 | + | |
84 | 90 | var container = h('Thread', [ |
85 | 91 | h('div.messages', [ |
86 | 92 | when(thread.branchId, h('a.full', {href: thread.rootId, anchor: id}, [i18n('View full thread')])), |
87 | 93 | map(thread.messages, (msg) => { |
modules/profile/async/suggest.js | ||
---|---|---|
@@ -13,26 +13,51 @@ | ||
13 | 13 | |
14 | 14 | exports.create = function (api) { |
15 | 15 | var suggestions = null |
16 | 16 | var recentSuggestions = null |
17 | + var following = null | |
17 | 18 | |
18 | 19 | return nest('profile.async.suggest', function () { |
19 | 20 | loadSuggestions() |
20 | - return function (word) { | |
21 | + return function (word, defaultItems) { | |
22 | + var defaultSuggestions = Array.isArray(defaultItems) && defaultItems.length ? suggestions().filter((item) => { | |
23 | + return matches(item.title, word) && defaultItems.includes(item.id) | |
24 | + }) : null | |
25 | + | |
21 | 26 | if (!word) { |
22 | - return recentSuggestions() | |
27 | + return defaultSuggestions || recentSuggestions() | |
23 | 28 | } else { |
24 | - return suggestions().filter((item) => { | |
25 | - return item.title.toLowerCase().startsWith(word.toLowerCase()) | |
29 | + var result = defaultSuggestions || [] | |
30 | + | |
31 | + // prioritize people you follow | |
32 | + suggestions().forEach((item) => { | |
33 | + if (following().includes(item.id) && matches(item.title, word) && !result.some(v => v.id === item.id)) { | |
34 | + result.push(item) | |
35 | + } | |
26 | 36 | }) |
37 | + | |
38 | + // next most recently active profiles | |
39 | + recentSuggestions().forEach((item) => { | |
40 | + if (matches(item.title, word) && !result.some(v => v.id === item.id)) { | |
41 | + result.push(item) | |
42 | + } | |
43 | + }) | |
44 | + | |
45 | + // fallback to everyone | |
46 | + suggestions().forEach((item) => { | |
47 | + if (matches(item.title, word) && !result.some(v => v.id === item.id)) { | |
48 | + result.push(item) | |
49 | + } | |
50 | + }) | |
51 | + return result | |
27 | 52 | } |
28 | 53 | } |
29 | 54 | }) |
30 | 55 | |
31 | 56 | function loadSuggestions () { |
32 | 57 | if (!suggestions) { |
33 | 58 | var id = api.keys.sync.id() |
34 | - var following = api.contact.obs.following(id) | |
59 | + following = api.contact.obs.following(id) | |
35 | 60 | var recentlyUpdated = api.profile.obs.recentlyUpdated() |
36 | 61 | var contacts = computed([following, recentlyUpdated], function (a, b) { |
37 | 62 | var result = Array.from(a) |
38 | 63 | b.forEach((item, i) => { |
@@ -42,9 +67,9 @@ | ||
42 | 67 | }) |
43 | 68 | return result |
44 | 69 | }) |
45 | 70 | |
46 | - recentSuggestions = map(computed(recentlyUpdated, (items) => Array.from(items).slice(0, 10)), suggestion, {idle: true}) | |
71 | + recentSuggestions = map(computed(recentlyUpdated, (items) => Array.from(items).slice(0, 40)), suggestion, {idle: true}) | |
47 | 72 | suggestions = map(contacts, suggestion, {idle: true}) |
48 | 73 | watch(recentSuggestions) |
49 | 74 | watch(suggestions) |
50 | 75 | } |
@@ -55,9 +80,10 @@ | ||
55 | 80 | return Struct({ |
56 | 81 | title: name, |
57 | 82 | id, |
58 | 83 | subtitle: id.substring(0, 10), |
59 | - value: computed([name, id], mention), | |
84 | + value: computed([name, id], mention, {idle: true}), | |
85 | + cls: computed([id, following], followingClass, {idle: true}), | |
60 | 86 | image: api.about.obs.imageUrl(id), |
61 | 87 | showBoth: true |
62 | 88 | }) |
63 | 89 | } |
@@ -65,4 +91,15 @@ | ||
65 | 91 | |
66 | 92 | function mention (name, id) { |
67 | 93 | return `[@${name}](${id})` |
68 | 94 | } |
95 | + | |
96 | +function followingClass (id, following) { | |
97 | + if (following.includes(id)) { | |
98 | + return 'following' | |
99 | + } | |
100 | +} | |
101 | + | |
102 | +function matches (title, match) { | |
103 | + if (!match) return true | |
104 | + return title.toLowerCase().startsWith(match.toLowerCase()) | |
105 | +} |
Built with git-ssb-web