Last active
November 26, 2018 06:00
-
-
Save carsonfarmer/e941f51e237aeb6e765977f6681143f9 to your computer and use it in GitHub Desktop.
Second app code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint no-undef: "error" */ | |
/* eslint-env browser */ | |
import 'babel-polyfill' | |
import qs from 'query-string' | |
import ko from 'knockout' | |
import 'knockout-mapping' | |
import getIpfs from './ipfs-promise' | |
import { defaultProfile } from './default-profile' | |
import $ from 'jQuery' | |
// Special handler for contenteditable elements | |
// Comes from: | |
// https://stackoverflow.com/questions/19370098/knockout-contenteditable-binding | |
// Don't worry about this for purposes of this tutorial | |
ko.bindingHandlers.editable = { | |
init: function (element, valueAccessor, allBindingsAccessor) { | |
// const value = ko.unwrap(valueAccessor()) | |
const lazy = allBindingsAccessor().lazy | |
$(element).on('input', function () { | |
if (this.isContentEditable && ko.isWriteableObservable(lazy)) { | |
console.log(this.innerHTML) | |
lazy(this.innerHTML) | |
} | |
}) | |
}, | |
update: function (element, valueAccessor) { | |
const value = ko.unwrap(valueAccessor()) | |
element.contentEditable = value | |
if (!element.isContentEditable) { | |
$(element).trigger('input') | |
} | |
} | |
} | |
// Don't update view until after we've updated model | |
ko.bindingHandlers.lazy = { | |
update: function (element, valueAccessor) { | |
const value = ko.unwrap(valueAccessor()) | |
if (!element.isContentEditable) { | |
element.innerHTML = value | |
} | |
} | |
} | |
// getProfileJSON is an async function that fetchs custom ipns json data | |
const getProfileJSON = async (ipfs, ipns) => { | |
// Resolve IPNS hash (this is a new feature!) | |
const name = await ipfs.name.resolve(`/ipns/${ipns}`) | |
// Now, fetch files... | |
const files = await ipfs.files.get(`${name.path}/json`) | |
// Extract binary file contents | |
const string = String.fromCharCode.apply(null, files[0].content) | |
// Parse/convert to JSON | |
return JSON.parse(string) | |
} | |
// setup is our async initializer function | |
const setup = async () => { | |
try { | |
// Get a reference to the running, or new, IPFS peer/node | |
const ipfs = await getIpfs() | |
// Grab query string to check who's profile we're viewing | |
const query = qs.parse(location.search) | |
// Grab id of this IPFS peer, to check if we're viewing our own profile | |
const id = await ipfs.id() | |
// User id that we will use to request profile information | |
const user = query.user ? query.user : id.id | |
// Some reporting to help us when developing | |
console.log(`Viewing profile for ${user} from peer with id ${id.id}`) | |
if (user === id.id) { | |
console.log('Viewing own profile, editing will be enabled!') | |
} | |
// Setup a viewModel based on our JSON structure | |
const viewModel = ko.mapping.fromJS(defaultProfile) | |
// Add extra observables for when we're loading or editing our profile | |
viewModel.state = {} | |
viewModel.state.loading = ko.observable(true) | |
viewModel.state.editing = ko.observable(false) | |
// Function to handle edit profile click | |
viewModel.handleEdit = async function () { | |
const editing = this.state.editing() | |
// Toggle our editing state | |
this.state.editing(!editing) | |
if (editing) { | |
// Export viewModel to JSON | |
const json = ko.mapping.toJSON(viewModel) | |
// IPFS add options, currently just defaults + dir wrapping | |
const options = { wrapWithDirectory: true, onlyHash: false, pin: true } | |
// Create binary buffer from JSON string | |
const buf = Buffer.from(json) | |
try { | |
// Add the new file (same as on desktop) | |
const res = await ipfs.files.add({ path: 'json', content: buf }, options) | |
// Publish new file to peer's PeerID | |
const pub = await ipfs.name.publish(res[1].hash) | |
console.log(`published '${pub.value}' to profile: ${pub.name}`) | |
window.alert(`published update for profile:\n${pub.name}`) | |
} catch (err) { | |
console.log(err) | |
} | |
} | |
} | |
// Apply the viewModel bindings | |
ko.applyBindings(viewModel) | |
try { | |
// Get profile information if available | |
const data = await getProfileJSON(ipfs, user) | |
// Update our existing viewModel target | |
ko.mapping.fromJS(data, viewModel) | |
} catch (err) { | |
console.log(`${err}: using default profile.`) | |
} | |
// Change the loading state to update the view | |
viewModel.state.loading(false) | |
} catch (err) { | |
console.log(err) | |
} | |
} | |
setup() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment