git ssb

16+

Dominic / patchbay



Commit 5b1b2d4716e2359e97b1954627726823ece10ec4

Merge pull request #138 from ssbc/save-filters

save filters
mix irving authored on 10/27/2017, 5:01:13 AM
GitHub committed on 10/27/2017, 5:01:13 AM
Parent: c4b43a52984fb502328f29c00cf9ca2d190110b3
Parent: 5d007658edb69eb3171a7255f17b784bb29f97e1

Files changed

app/html/app.jschanged
app/html/filter.jschanged
app/html/filter.mcsschanged
app/html/scroller.mcsschanged
app/page/channel.jschanged
app/page/channel.mcsschanged
app/page/page.mcsschanged
app/styles/mixins.jschanged
app/sync/initialise/settings.jsadded
package-lock.jsonchanged
package.jsonchanged
app/html/app.jsView
@@ -8,11 +8,12 @@
88 exports.needs = nest({
99 'app.async.catchLinkClick': 'first',
1010 'app.html.tabs': 'first',
1111 'app.page.errors': 'first',
12 + 'app.sync.catchKeyboardShortcut': 'first',
13 + 'app.sync.goTo': 'first',
14 + 'app.sync.initialise': 'first',
1215 'app.sync.window': 'reduce',
13- 'app.sync.goTo': 'first',
14- 'app.sync.catchKeyboardShortcut': 'first',
1516 'history.obs.location': 'first',
1617 'history.sync.push': 'first',
1718 'router.sync.router': 'first',
1819 'styles.css': 'reduce',
@@ -25,8 +26,10 @@
2526
2627 function app () {
2728 console.log("STARTING app")
2829
30 + api.app.sync.initialise()
31 +
2932 window = api.app.sync.window(window)
3033
3134 const css = values(api.styles.css()).join('\n')
3235 insertCss(css)
app/html/filter.jsView
@@ -1,17 +1,22 @@
11 const nest = require('depnest')
2-const { h, Value, when } = require('mutant')
2 +const { h, Value, when, computed } = require('mutant')
33 const Abort = require('pull-abortable')
44 const pull = require('pull-stream')
55 const addSuggest = require('suggest-box')
66 const { isFeed } = require('ssb-ref')
7 +const some = require('lodash/some')
8 +const get = require('lodash/get')
9 +const isEqual = require('lodash/isEqual')
710
811 exports.gives = nest('app.html.filter')
912
1013 exports.needs = nest({
11- 'about.async.suggest': 'first',
14 + 'channel.async.suggest': 'first',
1215 'contact.obs.following': 'first',
13- 'keys.sync.id': 'first'
16 + 'keys.sync.id': 'first',
17 + 'settings.obs.get': 'first',
18 + 'settings.sync.set': 'first'
1419 })
1520
1621 exports.create = function (api) {
1722 return nest({
@@ -22,118 +27,140 @@
2227 const showFilters = Value(false)
2328
2429 const myId = api.keys.sync.id()
2530 const peopleIFollow = api.contact.obs.following(myId)
26- const onlyPeopleIFollow = Value(false)
27- const onlyAuthor = Value()
2831
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)
32 + const { set } = api.settings.sync
3533
36- const authorInput = h('input', {
37- 'ev-keyup': (ev) => {
38- const author = ev.target.value
39- if (author && !isFeed(author)) return
34 + const filterSettings = api.settings.obs.get('filter')
4035
41- onlyAuthor.set(author)
42- draw()
43- }
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)
4459 })
4560
4661 const filterMenu = h('Filter', [
47- h('i', {
48- classList: when(showFilters, 'fa fa-filter -active', 'fa fa-filter'),
62 + when(isFiltered, h('i.custom')),
63 + h('i.fa.fa-filter', {
64 + classList: when(showFilters, '-active'),
4965 'ev-click': () => showFilters.set(!showFilters())
5066 }),
5167 h('i.fa.fa-angle-up', { 'ev-click': draw }),
52- h('div', { className: when(showFilters, '', '-hidden') }, [
68 + h('div.options', { className: when(showFilters, '', '-hidden') }, [
5369 h('header', [
5470 'Filter',
5571 h('i.fa.fa-filter')
5672 ]),
5773 h('section', [
58- h('div.author', [
59- h('label', 'Show author'),
60- authorInput
74 + h('div.channels', [
75 + h('label', 'Exclude channels'),
76 + channelInput
6177 ]),
62- toggle({ obs: onlyPeopleIFollow, label: 'Only people I follow' }),
78 + toggle({ type: 'peopleIFollow', filterGroup: 'only', label: 'Only people I follow' }),
6379 h('div.message-types', [
6480 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' })
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' })
7188 ])
7289 ])
7390 ])
7491 ])
7592
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- )
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 + ])
86117 }
87118
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))
119 + const getChannelSuggestions = api.channel.async.suggest()
120 + addSuggest(channelInput, (inputText, cb) => {
121 + if (inputText[0] === '#') {
122 + cb(null, getChannelSuggestions(inputText.slice(1)))
123 + }
93124 }, {cls: 'PatchSuggest'})
94- authorInput.addEventListener('suggestselect', ev => {
95- authorInput.value = ev.detail.id
125 + channelInput.addEventListener('suggestselect', ev => {
126 + const channels = channelInput.value.trim()
127 +
128 + api.settings.sync.set({ filter: { exclude: { channels: channels } } })
129 +
130 + draw()
96131 })
97132
98133 function followFilter (msg) {
99- if (!onlyPeopleIFollow()) return true
134 + if (!filterSettings().only.peopleIFollow) return true
100135
101136 return Array.from(peopleIFollow()).includes(msg.value.author)
102137 }
103138
104- function authorFilter (msg) {
105- if (!onlyAuthor()) return true
139 + function channelFilter (msg) {
140 + var filters = filterSettings().exclude.channels
141 + if (!filters) return true
142 + filters = filters.split(' ').map(c => c.slice(1))
106143
107- return msg.value.author === onlyAuthor()
144 + return msg.value.content && !filters.includes(msg.value.content.channel)
108145 }
109146
110147 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
148 + var { type } = msg.value.content
149 + if (/^chess/.test(type)) {
150 + type = 'chess'
126151 }
152 +
153 + return get(filterSettings(), ['show', type], true)
127154 }
128155
129156 var downScrollAborter
130157
131158 function filterDownThrough () {
132159 return pull(
133160 downScrollAborter,
134161 pull.filter(followFilter),
135- pull.filter(authorFilter),
162 + pull.filter(channelFilter),
136163 pull.filter(messageFilter)
137164 )
138165 }
139166
@@ -142,9 +169,9 @@
142169 function filterUpThrough () {
143170 return pull(
144171 upScrollAborter,
145172 pull.filter(followFilter),
146- pull.filter(authorFilter),
173 + pull.filter(channelFilter),
147174 pull.filter(messageFilter)
148175 )
149176 }
150177
app/html/filter.mcssView
@@ -1,9 +1,7 @@
11 Filter {
2- display: flex
3- flex-direction: column
4-
52 color: #444
3 + $threadWidth
64
75 i {
86 position: absolute
97 top: 3rem
@@ -21,14 +19,24 @@
2119 }
2220 i.fa-angle-up {
2321 left: 1rem
2422 }
23 + i.custom {
24 + right: 3.5rem
25 + font-size: .8rem
26 + color: #666
2527
26- div {
27- margin: 0 .5rem .5rem .5rem
28 + ::before {
29 + content: 'custom'
30 + }
31 + }
32 +
33 + div.options {
34 + background-color: #fff
35 +
2836 padding: .5rem
29- background-color: #fff
3037 border: 1px gainsboro solid
38 + margin: 0 .5rem .5rem .5rem
3139
3240 -hidden {
3341 height: 0
3442 display: none
@@ -48,9 +56,9 @@
4856 flex-wrap: wrap
4957 justify-content: space-between
5058 align-items: center
5159
52- div.author {
60 + div.channels {
5361 label {
5462 margin-right: .4rem
5563 }
5664 input {
app/html/scroller.mcssView
@@ -10,10 +10,9 @@
1010 div.wrapper {
1111 align-self: center
1212
1313 flex: 1 1
14- min-width: 780px
15- max-width: 840px
14 + $threadWidth
1615 padding-top: .5rem
1716
1817 section.content {
1918 div {
app/page/channel.jsView
@@ -40,9 +40,9 @@
4040 )
4141
4242 const composer = api.message.html.compose({ meta: { type: 'post', channel: channelName } })
4343 const { filterMenu, filterDownThrough, filterUpThrough, resetFeed } = api.app.html.filter(draw)
44- const { container, content } = api.app.html.scroller({ prepend: [subscribeButton, composer] })
44 + const { container, content } = api.app.html.scroller({ prepend: [subscribeButton, composer, filterMenu] })
4545
4646 function draw () {
4747 resetFeed({ container, content })
4848
@@ -62,13 +62,13 @@
6262 }
6363 draw()
6464
6565 var page = h('Page -channel', {title: channel}, [
66- filterMenu,
66 + // filterMenu, // TODO - extract non-scroller els like filterMenu here
6767 container
6868 ])
6969
70- // TODO better scroll hack for hekyboard shortcuts
70 + // TODO better scroll hack for keyboard shortcuts
7171 page.scroll = container.scroll
7272
7373 return page
7474 }
app/page/channel.mcssView
@@ -1,8 +1,5 @@
11 Page -channel {
2- div.Filter {
3- }
4-
52 div.Scroller {
63 div.wrapper {
74 header {
85 display: flex
app/page/page.mcssView
@@ -3,6 +3,7 @@
33
44 $backgroundPrimary
55
66 display: flex
7 + flex-wrap: wrap
78 }
89
app/styles/mixins.jsView
@@ -47,5 +47,10 @@
4747 $avatarSmall {
4848 width: 32px
4949 height: 32px
5050 }
51 +
52 +$threadWidth {
53 + min-width: 780px
54 + max-width: 840px
55 +}
5156 `
app/sync/initialise/settings.jsView
@@ -1,0 +1,42 @@
1 +const nest = require('depnest')
2 +const merge = require('lodash/merge')
3 +
4 +exports.gives = nest('app.sync.initialise')
5 +
6 +exports.needs = nest({
7 + 'settings.sync.set': 'first',
8 + 'settings.sync.get': 'first',
9 +})
10 +
11 +const defaults = {
12 + filter: {
13 + exclude: {
14 + channels: ""
15 + },
16 + only: {
17 + peopleIFollow: false
18 + },
19 + show: {
20 + post: true,
21 + vote: false, // a.k.a. like
22 + about: true,
23 + contact: false,
24 + channel: false,
25 + pub: false,
26 + chess: false
27 + }
28 + }
29 +}
30 +
31 +exports.create = function (api) {
32 + return nest('app.sync.initialise', initialiseSettings)
33 +
34 + function initialiseSettings () {
35 + const { get, set } = api.settings.sync
36 + const settings = merge({}, defaults, get())
37 + settings.filter.defaults = defaults.filter
38 +
39 + set(settings)
40 + }
41 +}
42 +
package-lock.jsonView
The diff is too large to show. Use a local git client to view these changes.
Old file size: 306362 bytes
New file size: 306362 bytes
package.jsonView
@@ -49,8 +49,9 @@
4949 "hyperlightbox": "^1.0.0",
5050 "hypertabs": "^5.0.0",
5151 "insert-css": "^2.0.0",
5252 "libnested": "^1.2.1",
53 + "lodash": "^4.17.4",
5354 "micro-css": "^2.0.1",
5455 "mutant": "^3.18.0",
5556 "mutant-pull-reduce": "^1.0.1",
5657 "open-external": "^0.1.1",

Built with git-ssb-web