git ssb

10+

Matt McKegg / patchwork



Tree: 0f55f6590b4fcc68e74c2910f6437b56f946b331

Files: 0f55f6590b4fcc68e74c2910f6437b56f946b331 / modules / profile / async / suggest.js

3030 bytesRaw
1var nest = require('depnest')
2var {Struct, map, computed, watch} = require('mutant')
3
4exports.needs = nest({
5 'profile.obs.recentlyUpdated': 'first',
6 'contact.obs.following': 'first',
7 'about.obs.name': 'first',
8 'about.obs.imageUrl': 'first',
9 'keys.sync.id': 'first'
10})
11
12exports.gives = nest('profile.async.suggest')
13
14exports.create = function (api) {
15 var suggestions = null
16 var recentSuggestions = null
17 var following = null
18
19 return nest('profile.async.suggest', function () {
20 loadSuggestions()
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
26 if (!word) {
27 return defaultSuggestions || recentSuggestions()
28 } else {
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 }
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
52 }
53 }
54 })
55
56 function loadSuggestions () {
57 if (!suggestions) {
58 var id = api.keys.sync.id()
59 following = api.contact.obs.following(id)
60 var recentlyUpdated = api.profile.obs.recentlyUpdated()
61 var contacts = computed([following, recentlyUpdated], function (a, b) {
62 var result = Array.from(a)
63 b.forEach((item, i) => {
64 if (!result.includes(item)) {
65 result.push(item)
66 }
67 })
68 return result
69 })
70
71 recentSuggestions = map(computed(recentlyUpdated, (items) => Array.from(items).slice(0, 40)), suggestion, {idle: true})
72 suggestions = map(contacts, suggestion, {idle: true})
73 watch(recentSuggestions)
74 watch(suggestions)
75 }
76 }
77
78 function suggestion (id) {
79 var name = api.about.obs.name(id)
80 return Struct({
81 title: name,
82 id,
83 subtitle: id.substring(0, 10),
84 value: computed([name, id], mention, {idle: true}),
85 cls: computed([id, following], followingClass, {idle: true}),
86 image: api.about.obs.imageUrl(id),
87 showBoth: true
88 })
89 }
90}
91
92function mention (name, id) {
93 return `[@${name}](${id})`
94}
95
96function followingClass (id, following) {
97 if (following.includes(id)) {
98 return 'following'
99 }
100}
101
102function matches (text, startsWith) {
103 return text.slice(0, startsWith.length).localeCompare(startsWith, 'default', {sensitivity: 'base'}) === 0
104}
105

Built with git-ssb-web