From 3fb754d9b7c4ccb9c5276dfba09cae6b7c2f446c Mon Sep 17 00:00:00 2001 From: natjms Date: Sat, 29 Jan 2022 12:34:11 -0800 Subject: [PATCH] Reset repo --- .gitignore | 4 ++ LICENSE | 30 ++++++++++ README.md | 1 + elm-package.json | 17 ++++++ js/index.js | 41 ++++++++++++++ package.json | 19 +++++++ src/Publish.elm | 144 +++++++++++++++++++++++++++++++++++++++++++++++ src/Retrieve.elm | 118 ++++++++++++++++++++++++++++++++++++++ www/index.html | 50 ++++++++++++++++ www/styles.css | 67 ++++++++++++++++++++++ www/u/index.html | 20 +++++++ www/u/styles.css | 70 +++++++++++++++++++++++ 12 files changed, 581 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 elm-package.json create mode 100644 js/index.js create mode 100644 package.json create mode 100644 src/Publish.elm create mode 100644 src/Retrieve.elm create mode 100644 www/index.html create mode 100644 www/styles.css create mode 100644 www/u/index.html create mode 100644 www/u/styles.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c231e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +elm.js +bundle.js +node_modules +elm-stuff diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d75b5a6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2018-present, natjms + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of natjms nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9c9f216 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# dbio - Share your bio via the InterPlanetary File System diff --git a/elm-package.json b/elm-package.json new file mode 100644 index 0000000..01d2350 --- /dev/null +++ b/elm-package.json @@ -0,0 +1,17 @@ +{ + "version": "1.0.0", + "summary": "", + "repository": "https://github.com/natjms/dbio.git", + "license": "BSD3", + "source-directories": [ + "." + ], + "exposed-modules": [], + "dependencies": { + "elm-lang/core": "5.1.1 <= v < 6.0.0", + "elm-lang/html": "2.0.0 <= v < 3.0.0", + "elm-lang/navigation": "2.0.0 <= v < 3.0.0", + "elm-community/html-extra": "2.2.0 <= v < 3.0.0" + }, + "elm-version": "0.18.0 <= v < 0.19.0" +} diff --git a/js/index.js b/js/index.js new file mode 100644 index 0000000..7f650c2 --- /dev/null +++ b/js/index.js @@ -0,0 +1,41 @@ +"use strict" + +const IpfsApi = require("ipfs-api"); +const ipfs = IpfsApi(); + +document.addEventListener("DOMContentLoaded", () => { + const home = document.getElementById("page_home"); + const view = document.getElementById("page_view"); + + const node = document.getElementById("elm"); + + if (home) + home_page(node); + + if (view) + view_page(node); +}); + +function home_page(node) { + const app = Elm.Publish.embed(node); + + app.ports.pub.subscribe(function(obj) { + const string = JSON.stringify(obj); + + const stored_hash = ipfs.add(Buffer.from(string)) + .catch(error => alert(error)) + .then(file => app.ports.new_hash.send(file[0].hash)); + }); +} + +function view_page(node) { + const app = Elm.Retrieve.embed(node); + const hash = window.location.hash.slice(1); + + ipfs.cat(hash, { buffer: true }) + .catch((error) => window.location.href = "../index.html") + .then((bio) => { + const as_string = new TextDecoder("utf-8").decode(bio) + app.ports.receive_bio.send(as_string) + }); +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f2cf1f6 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "dbio", + "version": "1.0.0", + "description": "Share your bio via IPFS", + "main": "index.js", + "scripts": { + "start": "http-server www -a 127.0.0.1 -p 3000", + "build": "browserify js/index.js > www/bundle.js && elm make src/Publish.elm --output=www/elm.js && elm make src/Retrieve.elm --output=www/u/elm.js" + }, + "keywords": [], + "author": "natjms", + "license": "BSD-3-Clause", + "devDependencies": { + "browserify": "^13.1.1", + "ipfs-api": "^11.1.0", + "http-server": "^0.9.0", + "elm": "^0.18.0" + } +} diff --git a/src/Publish.elm b/src/Publish.elm new file mode 100644 index 0000000..124d542 --- /dev/null +++ b/src/Publish.elm @@ -0,0 +1,144 @@ +port module Publish exposing (main) + +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput, onClick) +import Navigation exposing (load) + + +main = + Html.program + { view = view + , update = update + , init = init + , subscriptions = subscriptions + } + + +-- MODEL + +type alias Desc = + { name : String + , location : String + , image : String + , work : String + , education : String + , bio : String + } + +type alias Model = + { desc : Desc + } + +port pub : Desc -> Cmd msg + +init : (Model, Cmd Msg) +init = + ( { desc = + { name = "" + , location = "" + , image = "" + , work = "" + , education = "" + , bio = "" + } + } + , Cmd.none + ) + + +-- VIEW + + +view : Model -> Html Msg +view model = + div [] + [ input [ type_ "text", placeholder "Name", onInput Name] [] + , input [ type_ "text", placeholder "Location", onInput Location] [] + , input [ type_ "text", placeholder "IPFS image hash", onInput Image] [] + , div [ class "two-inputs" ] + [ input [ type_ "text", placeholder "Work", onInput Work] [] + , input [ type_ "text", placeholder "Education", onInput Education] [] + ] + , textarea [ placeholder "Talk about yourself", onInput Bio] [] + , input [ type_ "submit", value "Publish", onClick Submit] [] + ] + + + +-- UPDATE +updateName desc name = { desc | name = name } +updateImage desc img = { desc | image = img } +updateWork desc work = { desc | work = work } +updateEducation desc education = { desc | education = education } +updateLocation desc location = { desc | location = location } +updateBio desc bio = { desc | bio = bio } + +type Msg + = Name String + | Image String + | Work String + | Education String + | Location String + | Bio String + | Submit + | Navigate String + + +update : Msg -> Model -> (Model, Cmd msg) +update msg model = + case msg of + Name new -> + ( { model | + desc = updateName model.desc new + } + , Cmd.none + ) + Image new -> + ( { model | + desc = updateImage model.desc new + } + , Cmd.none + ) + Work new -> + ( { model | + desc = updateWork model.desc new + } + , Cmd.none + ) + Education new -> + ( { model | + desc = updateEducation model.desc new + } + , Cmd.none + ) + Location new -> + ( { model | + desc = updateLocation model.desc new + } + , Cmd.none + ) + Bio new -> + ( { model | + desc = updateBio model.desc new + } + , Cmd.none + ) + Submit -> + ( model + , pub model.desc + ) + Navigate hash -> + ( model + , load ("u/#" ++ hash) + ) + + +-- SUBSCRIPTIONS + + +port new_hash : (String -> msg) -> Sub msg + +subscriptions : Model -> Sub Msg +subscriptions model = + new_hash Navigate diff --git a/src/Retrieve.elm b/src/Retrieve.elm new file mode 100644 index 0000000..3b2f359 --- /dev/null +++ b/src/Retrieve.elm @@ -0,0 +1,118 @@ +port module Retrieve exposing (main) + +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput, onClick) +import Json.Decode exposing (..) +import Navigation exposing (load) +import Result exposing (withDefault) +import Html.Attributes.Extra exposing (innerHtml) + + +main = + Html.program + { view = view + , update = update + , init = init + , subscriptions = subscriptions + } + + +-- MODEL + +type alias Model = + { name : String + , location : String + , image : String + , work : String + , education : String + , bio : String + } + +init : (Model, Cmd Msg) +init = + ( { name = "" + , location = "" + , image = "" + , work = "" + , education = "" + , bio = "" + } + , Cmd.none + ) + + +-- VIEW + +ipfsGateway : String +ipfsGateway = "https://ipfs.io/ipfs/" + +view : Model -> Html Msg +view model = + div [ class "row" ] + [ div [ class "image col-md-8 col-sm-8" ] + [ img [ src (ipfsGateway ++ model.image) ] [] + ] + , div [ class "content col-md-4 col-sm-4"] + [ h1 [] [ text model.name ] + , p [ class "subheader" ] [ text model.location ] + , p [ innerHtml model.bio ] [] + , div [ class "container-fluid" ] + [ div [ class "row" ] + [ div [ class "col-md-6 col-sm-6" ] + [ h3 [] [ text "Work" ] + , p [] [ text model.work ] + ] + , div [ class "col-md-6 col-sm-6" ] + [ h3 [] [ text "Education" ] + , p [] [ text model.education ] + ] + ] + ] + ] + ] + + +-- UPDATE + +type Msg + = Retrieved String + | Error + +update : Msg -> Model -> (Model, Cmd msg) +update msg model = + case msg of + Retrieved json -> + ( { name = + decodeString (field "name" string) json + |> withDefault "Somebody" + , location = + decodeString (field "location" string) json + |> withDefault "Somewhere" + , image = + decodeString (field "image" string) json + |> withDefault "QmSVUVwKHMgBxy98N3vKkB6RQ4Umxd2mFd4uoMLpmqYKLW" + , work = + decodeString (field "work" string) json + |> withDefault "A job" + , education = + decodeString (field "education" string) json + |> withDefault "Some school" + , bio = + decodeString (field "bio" string) json + |> withDefault "Nothing to show..." + } + , Cmd.none + ) + Error -> + (model, load "../index.html") + + +-- SUBSCRIPTIONS + + +port receive_bio : (String -> msg) -> Sub msg + +subscriptions : Model -> Sub Msg +subscriptions model = + receive_bio Retrieved diff --git a/www/index.html b/www/index.html new file mode 100644 index 0000000..6023ee8 --- /dev/null +++ b/www/index.html @@ -0,0 +1,50 @@ + + + + + dbio + + + + +
+
+

+ dbio - decentralized profiles +

+
+ +
+
+
+
+
+
+
+
+
+
+

What is dbio?

+

+ Dbio is a simple tool, similar to about.me, that you can use to share + your bio. Unlike about.me, dbio users don't have to trust a central + server: all the content you publish is added to IPFS - the permanet + web. You seed your own bio from your own IPFS node. +

+ +

+ By the way, you can only publish to writeable nodes. Make sure the + gateway you're using is writeable! +

+
+
+ + + + + + diff --git a/www/styles.css b/www/styles.css new file mode 100644 index 0000000..7ff6d3b --- /dev/null +++ b/www/styles.css @@ -0,0 +1,67 @@ +body { + color: #2c3e50; +} + +.jumbotron { + background-color: #3498db; + height: 200px; + padding: 20px; +} + +.jumbotron h1 { + text-align: center; +} + +.form { + padding-top: 40px; + + padding-bottom: 60px; +} + +.form-inner { + width: 500px; + max-width: 90%; + margin: 0 auto +} + +input, textarea { + width: 100%; + padding: 10px; + border: none; + border-bottom: 1px solid black +} + +input[type=submit] { + border-bottom: none; + background-color: #3498db; + color: #2c3e50; + font-weight: bold +} + +.two-inputs > input { + width: 49% +} + +.two-inputs > input:last-child { + margin-left: 5px +} + +.about { + background-color: #ecf0f1; + padding-top: 10vh; + padding-bottom: 10vh; + font-size: 1.5em +} + +.about h2 { + font-size: 2em; + line-height: 2em; +} + +.footer { + padding-top: 10px; + font-size: 1.2em; + text-align: center; + background-color: #34495e; + color: #ecf0f1 +} diff --git a/www/u/index.html b/www/u/index.html new file mode 100644 index 0000000..fd38e71 --- /dev/null +++ b/www/u/index.html @@ -0,0 +1,20 @@ + + + + + dbio + + + + +
+ +
+
+
+
+ + + + + diff --git a/www/u/styles.css b/www/u/styles.css new file mode 100644 index 0000000..f35e2e9 --- /dev/null +++ b/www/u/styles.css @@ -0,0 +1,70 @@ +h1 { + text-transform: uppercase; +} + +h1 { + font-size: 2em +} + +h2, h3, h4, h5, h6 { + font-weight: bold; +} + +h2, .subheader { + font-weight: bold; + font-size: 1.5em; +} + +h3 { font-size: 1em } +h4 { font-size: 0.9em } +h5 { font-size: 0.8em } +h6 { font-size: 0.8em } + +.subheader { + font-size: 1.1em; + padding-bottom: 10px; +} + +.content { + padding: 50px; + overflow-y: scroll; +} + +.image { + height: 100vh; + background-position: center; + background-size: cover; + + padding: 0; + margin: 0; +} + +.image > img { + width: 100%; + height: 100vh; + object-fit: cover; +} + +.name { + font-size: 3em; +} + +.location { + font-size: 1.5em; + font-weight: bold; +} + +@media screen and (min-width: 768px) { + .content { + max-height: 100vh; + } +} + +@media screen and (max-width: 767px) { + .image { height: 50vh } + .image > img { height: 50vh } + + .content { + overflow-y: auto; + } +}