git ssb

16+

Dominic / patchbay



Tree: c1d6d6318ae0b3f8c151338aca3387cf51e77c15

Files: c1d6d6318ae0b3f8c151338aca3387cf51e77c15 / about / async / suggest.js

3772 bytesRaw
1var nest = require('depnest')
2var { h, Struct, map, concat, dictToCollection, computed, lookup, watch, keys, resolve } = require('mutant')
3
4var KEY_SAMPLE_LENGTH = 10 // includes @
5
6exports.gives = nest('about.async.suggest')
7
8exports.needs = nest({
9 'about.obs.groupedValues': 'first',
10 'about.obs.name': 'first',
11 'about.obs.imageUrl': 'first',
12 'contact.obs.following': 'first',
13 'feed.obs.recent': 'first',
14 'keys.sync.id': 'first'
15})
16
17exports.create = function (api) {
18 var suggestions = null
19 var recentSuggestions = null
20
21 return nest('about.async.suggest', suggest)
22
23 function suggest () {
24 loadSuggestions()
25 return function (word) {
26 if (!word) return recentSuggestions()
27
28 wordLower = word.toLowerCase()
29 return suggestions()
30 .filter(item => ~item.title.toLowerCase().indexOf(wordLower))
31 .sort((a, b) => {
32 // where name is matching exactly so far
33 if (a.title.indexOf(word) === 0) return -1
34 if (b.title.indexOf(word) === 0) return +1
35
36 // where name is matching exactly so far (case insensitive)
37 if (a.title.toLowerCase().indexOf(wordLower) === 0) return -1
38 if (b.title.toLowerCase().indexOf(wordLower) === 0) return +1
39 })
40 .reduce((sofar, match) => {
41 // prune down to the first instance of each id
42 // this presumes if you were typing e.g. "dino" you don't need "ahdinosaur" as well
43 if (sofar.find(el => el.id === match.id)) return sofar
44
45 return [...sofar, match]
46 }, [])
47 .sort((a, b) => {
48 // bubble up names where typed word matches our name for them
49 if (a._isPrefered) return -1
50 if (b._isPrefered) return +1
51 })
52 }
53 }
54
55 function loadSuggestions () {
56 if (suggestions) return
57
58 var id = api.keys.sync.id()
59 var following = api.contact.obs.following(id)
60 var recentlyUpdated = api.feed.obs.recent()
61 var contacts = computed([following, recentlyUpdated], (a, b) => {
62 var result = new Set(a)
63 b.forEach(item => result.add(item))
64
65 return Array.from(result)
66 })
67
68 recentSuggestions = map(
69 computed(recentlyUpdated, (items) => Array.from(items).slice(0, 10)),
70 suggestion,
71 {idle: true}
72 )
73
74 const suggestionsRecord = lookup(contacts, contact => {
75 return [contact, keys(api.about.obs.groupedValues(contact, 'name'))]
76 })
77
78 suggestions = concat(
79 map(dictToCollection(suggestionsRecord), pluralSuggestions, {idle: true})
80 )
81
82 watch(recentSuggestions)
83 watch(suggestions)
84 }
85
86 function pluralSuggestions (item) {
87 const id = resolve(item.key)
88
89 return computed([api.about.obs.name(id)], myNameForThem => {
90 return map(item.value, name => {
91 const names = item.value()
92
93 const aliases = names
94 .filter(n => n != name)
95 .map(name => h('div.alias',
96 { className: name === myNameForThem ? '-bold' : '' },
97 name
98 ))
99
100 return Struct({
101 id,
102 title: name,
103 subtitle: [
104 h('div.aliases', aliases),
105 h('div.key', id.substring(0, KEY_SAMPLE_LENGTH))
106 ],
107 value: mention(name, id),
108 image: api.about.obs.imageUrl(id),
109 showBoth: true,
110 _isPrefered: name === myNameForThem
111 })
112 })
113 })
114
115 }
116
117 // feeds recentSuggestions
118 function suggestion (id) {
119 var name = api.about.obs.name(id)
120 return Struct({
121 id,
122 title: name,
123 subtitle: h('div.key', id.substring(0, KEY_SAMPLE_LENGTH)),
124 value: computed([name, id], mention),
125 image: api.about.obs.imageUrl(id),
126 showBoth: true
127 })
128 }
129}
130
131function mention (name, id) {
132 return `[@${name}](${id})`
133}
134

Built with git-ssb-web