Skip to content

Instantly share code, notes, and snippets.

@mmckegg
Last active December 12, 2017 17:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmckegg/48c7cae54b75ab1a0b2d9789b0892b41 to your computer and use it in GitHub Desktop.
Save mmckegg/48c7cae54b75ab1a0b2d9789b0892b41 to your computer and use it in GitHub Desktop.
example bookmark flumeview-reduce with realtime updating
var nest = require('depnest')
var MutantPullReduce = require('mutant-pull-reduce')
exports.needs = nest({
'sbot.pull.stream': 'first'
})
exports.gives = nest('bookmarks.obs.all', true)
exports.create = function (api) {
var cached = null
return nest('bookmarks.obs.all', () => {
if (!cached) {
var stream = api.sbot.pull.stream(s => s.bookmarks.stream({live: true})
cached = MutantPullReduce(stream, (result, data) => {
if (data.bookmarks) {
// handle initial state
data.bookmarks.forEach(key => result.add(key))
} else if (data.key) {
// handle realtime changes
if (data.save) {
result.add(data.key)
} else {
result.delete(data.key)
}
}
return result
}, {
startValue: new Set()
})
}
return cached
})
}
var { watch } = require('mutant')
var nest = require('depnest')
exports.needs = nest({
'bookmarks.obs.all': 'first'
})
exports.gives = nest('bookmarks.obs.isSaved', true)
exports.create = function (api) {
var cache = null
var lookup = {}
return nest('bookmarks.obs.isSaved', (id) => {
if (!cache) loadCache()
if (!lookup[id]) {
lookup[id] = Value(cache().has(id))
}
return lookup[id]
})
function loadCache () {
cache = api.bookmarks.obs.all()
watch(cache, bookmarks => {
Object.keys(lookup).forEach(key => {
var value = bookmarks.has(key)
if (lookup[key]() !== value) {
lookup[key].set(value)
}
})
})
}
}
var { h, computed, when } = require('mutant')
var nest = require('depnest')
exports.needs = nest({
'keys.sync.id': 'first',
'bookmarks.obs.isSaved': 'first',
'sbot.async.publish': 'first'
})
exports.gives = nest('message.html.action')
exports.create = (api) => {
return nest('message.html.action', function saveAction (msg) {
var saved = api.bookmarks.obs.isSaved(msg.key)
return when(saved,
h('a.unsave', {
href: '#',
'ev-click': () => publishSave(msg.key, false)
}, 'Saved'),
h('a.save', {
href: '#',
'ev-click': () => publishSave(msg.key, true)
}, 'Save')
)
})
function publishSave (id, status = true) {
var yourId = api.keys.sync.id()
api.sbot.async.publish({
type: 'bookmark',
save: status,
recps: [yourId],
private: true
})
}
}
var { map, computed, h } = require('mutant')
exports.needs = nest({
'bookmarks.obs.all': 'first',
'message.obs.get': 'first',
'message.html.render': 'first'
})
exports.gives = nest('page.html.render', true)
exports.create = function (api) {
return nest('page.html.render', (path) => {
if (path !== '/bookmarks') return
var bookmarks = api.bookmarks.obs.all()
var resersed = computed(bookmarks, (bookmarks) => Array.from(bookmarks).reverse(), {idle: true})
var messages = map(bookmarks, key => api.message.obs.get(key))
return h('Page', [
h('section', [
map(messages, msg => {
// msg here is an observable, it will be resolved once message has loaded
// or could be a missing message
// eventually this will also handle lookup of out-of-order messages
return computed(msg, msg => {
if (msg && !msg.value.missing) {
message.html.render(msg)
}
})
})
])
])
})
}
// add this to sbot as a plugin
var FlumeviewReduce = require('flumeview-reduce')
exports.name = 'bookmarks'
exports.version = require('./package.json').version
exports.manifest = {
stream: 'source',
get: 'async'
}
exports.init = function (ssb, config) {
return ssb._flumeUse('bookmarks', FlumeReduce(0, reduce, map))
function reduce (result, item) {
if (!result) result = {}
if (!result.bookmarks) result.bookmarks = []
if (item) {
var index = result.bookmarks.indexOf(item.key)
if (item.save === true) {
if (index < 0) {
// remove the item
result.splice(index, 1)
}
} else if (item.save === false) {
if (index >= 0) {
// add the item
result.bookmarks.push(item.key)
}
}
}
}
function map (msg) {
// only include our bookmarks
if (msg.value.author !== ssb.id) return
// unbox private message
if (msg.value.content === 'string') {
// unbox private message (requires ssb-private plugin)
msg = ssb.private.unbox(msg)
}
// make sure it is a bookmark
if (msg && msg.value.content.type === 'bookmark' && typeof msg.value.content.save === 'boolean') {
return {
key: msg.value.content.bookmark
save: msg.value.content.save
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment