git ssb

0+

mixmix / patch-suggest



Tree: b39553f9cc66a675cc0573bf64b08ef39414ba3c

Files: b39553f9cc66a675cc0573bf64b08ef39414ba3c / channel / async / suggest.js

2544 bytesRaw
1const nest = require('depnest')
2const { computed, watch, map, Struct } = require('mutant')
3
4exports.gives = nest('channel.async.suggest')
5
6exports.needs = nest({
7 'channel.obs': {
8 recent: 'first',
9 subscribed: 'first'
10 },
11 'keys.sync.id': 'first'
12})
13
14exports.create = function (api) {
15 var suggestions = null
16 var subscribed = null
17
18 return nest('channel.async.suggest', suggestedChannels)
19
20 function suggestedChannels (word, cb) {
21 loadSuggestions()
22 if (word === null) return
23
24 if (!word) {
25 return suggestions()
26 .sort(() => Math.random() > 0.5 ? +1 : -1) // shuffle
27 .slice(0, 100)
28 }
29
30 const wordNormed = normalise(word)
31
32 const results = suggestions()
33 .filter(item => ~normalise(item.title).indexOf(word))
34 .sort((a, b) => {
35 // where name is is an exact match
36 if (a.title === word) return -1
37 if (b.title === word) return +1
38
39 // TODO - move all this into the suggestion building and decorate the suggestion?
40 const normedATitle = normalise(a.title)
41 const normedBTitle = normalise(b.title)
42
43 // where normalised name is an exact match
44 if (normedATitle === wordNormed) return -1
45 if (normedBTitle === wordNormed) return +1
46
47 // where name is matching exactly so far
48 if (a.title.indexOf(word) === 0) return -1
49 if (b.title.indexOf(word) === 0) return +1
50
51 // where name is matching exactly so far (case insensitive)
52 if (normedATitle.indexOf(wordNormed) === 0) return -1
53 if (normedBTitle.indexOf(wordNormed) === 0) return +1
54 })
55 cb(null, results)
56 }
57
58 function loadSuggestions () {
59 if (suggestions) return
60
61 var id = api.keys.sync.id()
62 subscribed = api.channel.obs.subscribed(id)
63 var recentlyUpdated = api.channel.obs.recent()
64 var channels = computed([subscribed, recentlyUpdated], function (a, b) {
65 var result = Array.from(a)
66 b.forEach((item, i) => {
67 if (!result.includes(item)) {
68 result.push(item)
69 }
70 })
71 return result
72 })
73
74 suggestions = map(channels, suggestion, {idle: true})
75 watch(suggestions)
76 }
77
78 function suggestion (id) {
79 return Struct({
80 title: id,
81 id: `#${id}`,
82 subtitle: computed([id, subscribed], subscribedCaption),
83 value: `#${id}`
84 })
85 }
86}
87
88function subscribedCaption (id, subscribed) {
89 if (subscribed.has(id)) {
90 return 'subscribed'
91 }
92}
93
94function normalise (word) {
95 return word.toLowerCase() //.replace(/(\s|-)/g, '')
96}
97

Built with git-ssb-web