Files: b39553f9cc66a675cc0573bf64b08ef39414ba3c / channel / async / suggest.js
2544 bytesRaw
1 | const nest = require('depnest') |
2 | const { computed, watch, map, Struct } = require('mutant') |
3 | |
4 | exports.gives = nest('channel.async.suggest') |
5 | |
6 | exports.needs = nest({ |
7 | 'channel.obs': { |
8 | recent: 'first', |
9 | subscribed: 'first' |
10 | }, |
11 | 'keys.sync.id': 'first' |
12 | }) |
13 | |
14 | exports.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 | |
88 | function subscribedCaption (id, subscribed) { |
89 | if (subscribed.has(id)) { |
90 | return 'subscribed' |
91 | } |
92 | } |
93 | |
94 | function normalise (word) { |
95 | return word.toLowerCase() //.replace(/(\s|-)/g, '') |
96 | } |
97 |
Built with git-ssb-web