git ssb

16+

Dominic / patchbay



Tree: a20d5059cc43f723aefd7fe6e3a79aa751ded3a9

Files: a20d5059cc43f723aefd7fe6e3a79aa751ded3a9 / app / html / filter.js

5303 bytesRaw
1const nest = require('depnest')
2const { h, Value, when, computed } = require('mutant')
3const Abort = require('pull-abortable')
4const pull = require('pull-stream')
5const addSuggest = require('suggest-box')
6const { isFeed } = require('ssb-ref')
7const some = require('lodash/some')
8const get = require('lodash/get')
9const isEqual = require('lodash/isEqual')
10
11exports.gives = nest('app.html.filter')
12
13exports.needs = nest({
14 'channel.async.suggest': 'first',
15 'contact.obs.following': 'first',
16 'keys.sync.id': 'first',
17 'settings.obs.get': 'first',
18 'settings.sync.set': 'first'
19})
20
21exports.create = function (api) {
22 return nest({
23 'app.html.filter': Filter
24 })
25
26 function Filter (draw) {
27 const showFilters = Value(false)
28
29 const myId = api.keys.sync.id()
30 const peopleIFollow = api.contact.obs.following(myId)
31
32 const { set } = api.settings.sync
33
34 const filterSettings = api.settings.obs.get('filter')
35
36 const channelInput = h('input',
37 { value: filterSettings().exclude.channels,
38 'ev-keyup': (ev) => {
39 var text = ev.target.value
40 if (text.length == 0 || ev.which == 13) {
41 api.settings.sync.set({
42 filter: {
43 exclude: {
44 channels: text
45 }
46 }
47 })
48 draw()
49 }
50 }
51 }
52 )
53
54 const isFiltered = computed(filterSettings, (filterSettings) => {
55 const _settings = Object.assign({}, filterSettings)
56 delete _settings.defaults
57
58 return !isEqual(_settings, filterSettings.defaults)
59 })
60
61 const filterMenu = h('Filter', [
62 when(isFiltered, h('i.custom')),
63 h('i.fa.fa-filter', {
64 classList: when(showFilters, '-active'),
65 'ev-click': () => showFilters.set(!showFilters())
66 }),
67 h('i.fa.fa-angle-up', { 'ev-click': draw }),
68 h('div.options', { className: when(showFilters, '', '-hidden') }, [
69 h('header', [
70 'Filter',
71 h('i.fa.fa-filter')
72 ]),
73 h('section', [
74 h('div.channels', [
75 h('label', 'Exclude channels'),
76 channelInput
77 ]),
78 toggle({ type: 'peopleIFollow', filterGroup: 'only', label: 'Only people I follow' }),
79 h('div.message-types', [
80 h('header', 'Show messages'),
81 toggle({ type: 'post' }),
82 toggle({ type: 'like' }),
83 toggle({ type: 'about' }),
84 toggle({ type: 'contact' }),
85 toggle({ type: 'channel' }),
86 toggle({ type: 'pub' }),
87 toggle({ type: 'chess' })
88 ])
89 ])
90 ])
91 ])
92
93 function toggle ({ type, filterGroup, label }) {
94 label = label || type
95 filterGroup = filterGroup || 'show'
96
97 const state = computed(filterSettings, settings => get(settings, [filterGroup, type]))
98 const handleClick = () => {
99 const currentState = state()
100
101 // TODO use some lodash tool ?
102 api.settings.sync.set({
103 filter: {
104 [filterGroup]: {
105 [type]: !currentState
106 }
107 }
108 })
109
110 draw()
111 }
112
113 return h('FilterToggle', { 'ev-click': handleClick }, [
114 h('label', label),
115 h('i', { classList: when(state, 'fa fa-check-square-o', 'fa fa-square-o') })
116 ])
117 }
118
119 const getChannelSuggestions = api.channel.async.suggest()
120 addSuggest(channelInput, (inputText, cb) => {
121 if (inputText[0] === '#') {
122 cb(null, getChannelSuggestions(inputText.slice(1)))
123 }
124 }, {cls: 'PatchSuggest'})
125 channelInput.addEventListener('suggestselect', ev => {
126 const channels = channelInput.value.trim()
127
128 api.settings.sync.set({ filter: { exclude: { channels: channels } } })
129
130 draw()
131 })
132
133 function followFilter (msg) {
134 if (!filterSettings().only.peopleIFollow) return true
135
136 return Array.from(peopleIFollow()).concat(myId).includes(msg.value.author)
137 }
138
139 function channelFilter (msg) {
140 var filters = filterSettings().exclude.channels
141 if (!filters) return true
142 filters = filters.split(' ').map(c => c.slice(1))
143
144 return msg.value.content && !filters.includes(msg.value.content.channel)
145 }
146
147 function messageFilter (msg) {
148 var { type } = msg.value.content
149 if (/^chess/.test(type)) {
150 type = 'chess'
151 }
152
153 return get(filterSettings(), ['show', type], true)
154 }
155
156 var downScrollAborter
157
158 function filterDownThrough () {
159 return pull(
160 downScrollAborter,
161 pull.filter(followFilter),
162 pull.filter(channelFilter),
163 pull.filter(messageFilter)
164 )
165 }
166
167 var upScrollAborter
168
169 function filterUpThrough () {
170 return pull(
171 upScrollAborter,
172 pull.filter(followFilter),
173 pull.filter(channelFilter),
174 pull.filter(messageFilter)
175 )
176 }
177
178 function resetFeed ({ container, content }) {
179 if (typeof upScrollAborter === 'function') {
180 upScrollAborter.abort()
181 downScrollAborter.abort()
182 }
183 upScrollAborter = Abort()
184 downScrollAborter = Abort()
185
186 container.scroll(0)
187 content.innerHTML = ''
188 }
189
190 return {
191 filterMenu,
192 filterDownThrough,
193 filterUpThrough,
194 resetFeed
195 }
196 }
197}
198

Built with git-ssb-web