Files: 10f58a04da1ab33c03a561753d15c0f77098cbbb / modules / profile / async / suggest.js
2957 bytesRaw
1 | var nest = require('depnest') |
2 | var {Struct, map, computed, watch} = require('mutant') |
3 | |
4 | exports.needs = nest({ |
5 | 'profile.obs.recentlyUpdated': 'first', |
6 | 'contact.obs.following': 'first', |
7 | 'about.obs.name': 'first', |
8 | 'about.obs.imageUrl': 'first', |
9 | 'intl.sync.startsWith': 'first', |
10 | 'keys.sync.id': 'first' |
11 | }) |
12 | |
13 | exports.gives = nest('profile.async.suggest') |
14 | |
15 | exports.create = function (api) { |
16 | var suggestions = null |
17 | var recentSuggestions = null |
18 | var following = null |
19 | var matches = api.intl.sync.startsWith |
20 | |
21 | return nest('profile.async.suggest', function () { |
22 | loadSuggestions() |
23 | return function (word, defaultItems) { |
24 | var defaultSuggestions = Array.isArray(defaultItems) && defaultItems.length ? suggestions().filter((item) => { |
25 | return matches(item.title, word) && defaultItems.includes(item.id) |
26 | }) : null |
27 | |
28 | if (!word) { |
29 | return defaultSuggestions || recentSuggestions() |
30 | } else { |
31 | var result = defaultSuggestions || [] |
32 | |
33 | // prioritize people you follow |
34 | suggestions().forEach((item) => { |
35 | if (following().includes(item.id) && matches(item.title, word) && !result.some(v => v.id === item.id)) { |
36 | result.push(item) |
37 | } |
38 | }) |
39 | |
40 | // next most recently active profiles |
41 | recentSuggestions().forEach((item) => { |
42 | if (matches(item.title, word) && !result.some(v => v.id === item.id)) { |
43 | result.push(item) |
44 | } |
45 | }) |
46 | |
47 | // fallback to everyone |
48 | suggestions().forEach((item) => { |
49 | if (matches(item.title, word) && !result.some(v => v.id === item.id)) { |
50 | result.push(item) |
51 | } |
52 | }) |
53 | return result |
54 | } |
55 | } |
56 | }) |
57 | |
58 | function loadSuggestions () { |
59 | if (!suggestions) { |
60 | var id = api.keys.sync.id() |
61 | following = api.contact.obs.following(id) |
62 | var recentlyUpdated = api.profile.obs.recentlyUpdated() |
63 | var contacts = computed([following, recentlyUpdated], function (a, b) { |
64 | var result = Array.from(a) |
65 | b.forEach((item, i) => { |
66 | if (!result.includes(item)) { |
67 | result.push(item) |
68 | } |
69 | }) |
70 | return result |
71 | }) |
72 | |
73 | recentSuggestions = map(computed(recentlyUpdated, (items) => Array.from(items).slice(0, 40)), suggestion, {idle: true}) |
74 | suggestions = map(contacts, suggestion, {idle: true}) |
75 | watch(recentSuggestions) |
76 | watch(suggestions) |
77 | } |
78 | } |
79 | |
80 | function suggestion (id) { |
81 | var name = api.about.obs.name(id) |
82 | return Struct({ |
83 | title: name, |
84 | id, |
85 | subtitle: id.substring(0, 10), |
86 | value: computed([name, id], mention, {idle: true}), |
87 | cls: computed([id, following], followingClass, {idle: true}), |
88 | image: api.about.obs.imageUrl(id), |
89 | showBoth: true |
90 | }) |
91 | } |
92 | } |
93 | |
94 | function mention (name, id) { |
95 | return `[@${name}](${id})` |
96 | } |
97 | |
98 | function followingClass (id, following) { |
99 | if (following.includes(id)) { |
100 | return 'following' |
101 | } |
102 | } |
103 |
Built with git-ssb-web