Files: 8e75010c68d2c079e58d57c19ae1919e2b878d31 / app / html / filter.js
4493 bytesRaw
1 | const nest = require('depnest') |
2 | const { h, Value, when } = require('mutant') |
3 | const Abort = require('pull-abortable') |
4 | const pull = require('pull-stream') |
5 | const addSuggest = require('suggest-box') |
6 | const { isFeed } = require('ssb-ref') |
7 | |
8 | exports.gives = nest('app.html.filter') |
9 | |
10 | exports.needs = nest({ |
11 | 'about.async.suggest': 'first', |
12 | 'contact.obs.following': 'first', |
13 | 'keys.sync.id': 'first' |
14 | }) |
15 | |
16 | exports.create = function (api) { |
17 | return nest({ |
18 | 'app.html.filter': Filter |
19 | }) |
20 | |
21 | function Filter (draw) { |
22 | const showFilters = Value(false) |
23 | |
24 | const myId = api.keys.sync.id() |
25 | const peopleIFollow = api.contact.obs.following(myId) |
26 | const onlyPeopleIFollow = Value(false) |
27 | const onlyAuthor = Value() |
28 | |
29 | const showPost = Value(true) |
30 | const showAbout = Value(true) |
31 | const showVote = Value(false) |
32 | const showContact = Value(false) |
33 | const showChannel = Value(false) |
34 | const showPub = Value(false) |
35 | |
36 | const authorInput = h('input', { |
37 | 'ev-keyup': (ev) => { |
38 | const author = ev.target.value |
39 | if (author && !isFeed(author)) return |
40 | |
41 | onlyAuthor.set(author) |
42 | draw() |
43 | } |
44 | }) |
45 | |
46 | const filterMenu = h('Filter', [ |
47 | h('i', { |
48 | classList: when(showFilters, 'fa fa-filter -active', 'fa fa-filter'), |
49 | 'ev-click': () => showFilters.set(!showFilters()) |
50 | }), |
51 | h('i.fa.fa-angle-up', { 'ev-click': draw }), |
52 | h('div', { className: when(showFilters, '', '-hidden') }, [ |
53 | h('header', [ |
54 | 'Filter', |
55 | h('i.fa.fa-filter') |
56 | ]), |
57 | h('section', [ |
58 | h('div.author', [ |
59 | h('label', 'Show author'), |
60 | authorInput |
61 | ]), |
62 | toggle({ obs: onlyPeopleIFollow, label: 'Only people I follow' }), |
63 | h('div.message-types', [ |
64 | h('header', 'Show messages'), |
65 | toggle({ obs: showPost, label: 'post' }), |
66 | toggle({ obs: showVote, label: 'like' }), |
67 | toggle({ obs: showAbout, label: 'about' }), |
68 | toggle({ obs: showContact, label: 'contact' }), |
69 | toggle({ obs: showChannel, label: 'channel' }), |
70 | toggle({ obs: showPub, label: 'pub' }) |
71 | ]) |
72 | ]) |
73 | ]) |
74 | ]) |
75 | |
76 | function toggle ({ obs, label }) { |
77 | return h('FilterToggle', { |
78 | 'ev-click': () => { |
79 | obs.set(!obs()) |
80 | draw() |
81 | }}, [ |
82 | h('label', label), |
83 | h('i', { classList: when(obs, 'fa fa-check-square-o', 'fa fa-square-o') }) |
84 | ] |
85 | ) |
86 | } |
87 | |
88 | // NOTE: suggest needs to be added after the input has a parent |
89 | const getProfileSuggestions = api.about.async.suggest() |
90 | addSuggest(authorInput, (inputText, cb) => { |
91 | if (inputText[0] === '@') inputText = inputText.slice(1) |
92 | cb(null, getProfileSuggestions(inputText)) |
93 | }, {cls: 'SuggestBox'}) |
94 | authorInput.addEventListener('suggestselect', ev => { |
95 | authorInput.value = ev.detail.id |
96 | }) |
97 | |
98 | function followFilter (msg) { |
99 | if (!onlyPeopleIFollow()) return true |
100 | |
101 | return Array.from(peopleIFollow()).includes(msg.value.author) |
102 | } |
103 | |
104 | function authorFilter (msg) { |
105 | if (!onlyAuthor()) return true |
106 | |
107 | return msg.value.author === onlyAuthor() |
108 | } |
109 | |
110 | function messageFilter (msg) { |
111 | switch (msg.value.content.type) { |
112 | case 'post': |
113 | return showPost() |
114 | case 'vote': |
115 | return showVote() |
116 | case 'about': |
117 | return showAbout() |
118 | case 'contact': |
119 | return showContact() |
120 | case 'channel': |
121 | return showChannel() |
122 | case 'pub': |
123 | return showPub() |
124 | default: |
125 | return true |
126 | } |
127 | } |
128 | |
129 | var downScrollAborter |
130 | |
131 | function filterDownThrough () { |
132 | return pull( |
133 | downScrollAborter, |
134 | pull.filter(followFilter), |
135 | pull.filter(authorFilter), |
136 | pull.filter(messageFilter) |
137 | ) |
138 | } |
139 | |
140 | var upScrollAborter |
141 | |
142 | function filterUpThrough () { |
143 | return pull( |
144 | upScrollAborter, |
145 | pull.filter(followFilter), |
146 | pull.filter(authorFilter), |
147 | pull.filter(messageFilter) |
148 | ) |
149 | } |
150 | |
151 | function resetFeed ({ container, content }) { |
152 | if (typeof upScrollAborter === 'function') { |
153 | upScrollAborter.abort() |
154 | downScrollAborter.abort() |
155 | } |
156 | upScrollAborter = Abort() |
157 | downScrollAborter = Abort() |
158 | |
159 | container.scroll(0) |
160 | content.innerHTML = '' |
161 | } |
162 | |
163 | return { |
164 | filterMenu, |
165 | filterDownThrough, |
166 | filterUpThrough, |
167 | resetFeed |
168 | } |
169 | } |
170 | } |
171 |
Built with git-ssb-web