Files: 17137bf4950b512a952c46b8d1a92203756ed979 / app / html / filter.js
4574 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(true) |
32 | const showContact = Value(true) |
33 | const showChannel = Value(true) |
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('div', { className: when(showFilters, '', '-hidden') }, [ |
52 | h('header', [ |
53 | 'Filter', |
54 | h('i.fa.fa-filter') |
55 | ]), |
56 | h('section', [ |
57 | h('div.author', [ |
58 | h('label', 'Show author'), |
59 | authorInput |
60 | ]), |
61 | toggle({ obs: onlyPeopleIFollow, label: 'Only people I follow' }), |
62 | h('div.refresh', { 'ev-click': draw }, [ |
63 | h('label', 'refresh'), |
64 | h('i.fa.fa-refresh') |
65 | ]), |
66 | h('div.message-types', [ |
67 | h('header', 'Show messages'), |
68 | toggle({ obs: showPost, label: 'post' }), |
69 | toggle({ obs: showVote, label: 'like' }), |
70 | toggle({ obs: showAbout, label: 'about' }), |
71 | toggle({ obs: showContact, label: 'contact' }), |
72 | toggle({ obs: showChannel, label: 'channel' }), |
73 | toggle({ obs: showPub, label: 'pub' }) |
74 | ]) |
75 | ]) |
76 | ]) |
77 | ]) |
78 | |
79 | function toggle ({ obs, label }) { |
80 | return h('FilterToggle', { |
81 | 'ev-click': () => { |
82 | obs.set(!obs()) |
83 | draw() |
84 | }}, [ |
85 | h('label', label), |
86 | h('i', { classList: when(obs, 'fa fa-check-square-o', 'fa fa-square-o') }) |
87 | ] |
88 | ) |
89 | } |
90 | |
91 | // NOTE: suggest needs to be added after the input has a parent |
92 | const getProfileSuggestions = api.about.async.suggest() |
93 | addSuggest(authorInput, (inputText, cb) => { |
94 | if (inputText[0] === '@') inputText = inputText.slice(1) |
95 | cb(null, getProfileSuggestions(inputText)) |
96 | }, {cls: 'SuggestBox'}) |
97 | authorInput.addEventListener('suggestselect', ev => { |
98 | authorInput.value = ev.detail.id |
99 | }) |
100 | |
101 | function followFilter (msg) { |
102 | if (!onlyPeopleIFollow()) return true |
103 | |
104 | return Array.from(peopleIFollow()).includes(msg.value.author) |
105 | } |
106 | |
107 | function authorFilter (msg) { |
108 | if (!onlyAuthor()) return true |
109 | |
110 | return msg.value.author === onlyAuthor() |
111 | } |
112 | |
113 | function messageFilter (msg) { |
114 | switch (msg.value.content.type) { |
115 | case 'post': |
116 | return showPost() |
117 | case 'vote': |
118 | return showVote() |
119 | case 'about': |
120 | return showAbout() |
121 | case 'contact': |
122 | return showContact() |
123 | case 'channel': |
124 | return showChannel() |
125 | case 'pub': |
126 | return showPub() |
127 | default: |
128 | return true |
129 | |
130 | } |
131 | } |
132 | |
133 | var downScrollAborter |
134 | |
135 | function filterDownThrough () { |
136 | return pull( |
137 | downScrollAborter, |
138 | pull.filter(followFilter), |
139 | pull.filter(authorFilter), |
140 | pull.filter(messageFilter) |
141 | ) |
142 | } |
143 | |
144 | var upScrollAborter |
145 | |
146 | function filterUpThrough () { |
147 | return pull( |
148 | upScrollAborter, |
149 | pull.filter(followFilter), |
150 | pull.filter(authorFilter), |
151 | pull.filter(messageFilter) |
152 | ) |
153 | } |
154 | |
155 | function resetFeed ({ container, content }) { |
156 | if (typeof upScrollAborter === 'function') { |
157 | upScrollAborter.abort() |
158 | downScrollAborter.abort() |
159 | } |
160 | upScrollAborter = Abort() |
161 | downScrollAborter = Abort() |
162 | |
163 | container.scroll(0) |
164 | content.innerHTML = '' |
165 | } |
166 | |
167 | return { |
168 | filterMenu, |
169 | filterDownThrough, |
170 | filterUpThrough, |
171 | resetFeed |
172 | } |
173 | } |
174 | } |
175 | |
176 |
Built with git-ssb-web