How to build a decentralized microblog with multi-player storage | Blockstack Tutorial(멀티 플레이어 스토리지 분산된 microblog 구축 하는 방법)

in #blockchain7 years ago (edited)

https://www.youtube.com/watch?time_continue=4&v=w7Sa54H-CGg


멀티 플레이어 스토리지 자습서
이 튜토리얼에서 우리는 멀티 플레이어 가이아 스토리지를 사용 하 여 분산 된 마이크로-블로깅 응용 프로그램 구축을 거 야.
이 애플 리 케이이 션 React.js 응용 프로그램을 완전히 분산 및 서버가 없는 것입니다. Id 및 스토리지 서비스 blockstack.js에 의해 제공 됩니다.
App은 다음을 수행할 수 있을 것입니다.
Blockstack를 사용 하 여 사용자 인증
포스트 새로운 상태
사용자 프로필에 상태 표시
조회 다른 사용자가 자신의 프로필 및 상태 보고
우리는 다음과 같은 도구가 사용할 것입니다.
종속성 및 스크립트를 관리 하는 고궁
요 반응 하는 Blockstack 응용 프로그램에 대 한 상용구 생성 하
인증 사용자 및 액세스 가이아 스토리지 blockstack.js
경험 있는 Blockstack 개발자, TL; DR:
로그인 요청에 publish_data 범위 추가
GetFile 사용 ('filename.json ', {사용자: 'username.id', 해독: false}) 다른 사용자 로부터 파일을 읽을 수.
LookupProfile('username.id') 조회 사용자 프로필을 사용 하 여
PutFile 사용 ('filename.json ', 파일, 옵션) 옵션 설정 되어 있는 전에 {암호화: false} 암호화가 해제 되 고 다른 파일을 읽을 수 있도록.
설치 및 생성
첫째, Blockstack 응용 프로그램 생성기 함께 유사시 설치:


npm install -g yo generator-blockstack


다음으로, 우리의 응용 프로그램에 대 한 디렉터리를 만듭니다. 우리는 우리의 애플 리 케이 션 Publik 호출 됩니다.


mkdir publik && cd publik


다음, Blockstack 반응 응용 프로그램 생성기를 사용 하 여 간단한 Blockstack 응용 프로그램을 생성 하기 위해:


yo blockstack:react


프롬프트에 응답 하는 후 응용 프로그램 생성기를 모든 응용 프로그램 파일을 만들고 모든 종속성을 설치.
로컬로 응용 프로그램 실행:


npm start


멀티 플레이어 저장 범위
멀티 플레이어 저장, 가이아에 저장 된 사용자 파일 사용자의 profile.json 파일에 애플 리 케이 션 속성을 통해 다른 사람에 게 보이는 만들어집니다. 모든 응용 프로그램을 멀티 플레이어 저장소를 사용 하 여 사용자의 profile.json 파일을 자체를 추가 해야 합니다. Blockstack 브라우저 인증 중 publish_data 범위 요청 될 때 자동으로이 부분을 처리 합니다.
그래서 우리가 해야 할 첫 번째 일은 우리의 인증 요청 publish_data 범위를 포함 하도록 수정 합니다.
Src/components/App.jsx를 열고 처리기 메서드에 기호를 찾습니다.


handleSignIn(e) {  e.preventDefault();  redirectToSignIn(); }


이 메서드를 수정:

handleSignIn(e) {  e.preventDefault();  const origin = window.location.origin  redirectToSignIn(origin, origin + '/manifest.json', ['store_write', 'publish_data']) }


기본적으로 인증 요청 저장을 가능 하 게 store_write 범위 포함 note.
로그 아웃 하 고 다시 로그인 하는 경우 인증 요청 이제 우리의 애플 리 케이 션에 대 한 저장 된 데이터를 게시 하려면 사용자를 자극할 것 이다.




게시 상태
이 단계에서 우리는 게시 하 고 "상태"의 표시를 허용 하도록 기능을 추가 합니다.
하자 src/components/Profile.jsx를 열고 blockstack.js에서 여러 가지 방법을 사용 하 게 될 것을 가져오기. 이 메서드는 putFile(), getFile() 및 lookupProfile(). Blockstack는 파일의 위쪽에 대 한 import 문을 추가할:


import {  isSignInPending,  loadUserData,  Person,  getFile,  putFile,  lookupProfile } from 'blockstack';


다음, 우리는 몇 가지 속성을 추가 해야 합니다 constructor()에서 초기 상태. 생성자는 다음과 같이 한다:


constructor(props) {  super(props);  this.state = {    person: {      name() {        return 'Anonymous';      },      avatarUrl() {        return avatarFallbackImage;      },    },    username: "",    newStatus: "",    statuses: [],    statusIndex: 0,    isLoading: false      }; }


이제 텍스트 입력을 추가 하 여 상태를 게시할 수 있도록 버튼을 제출 render() 메서드를 수정 하자. 다음으로 render() 메서드를 바꿉니다.


render() {  const { handleSignOut } = this.props;  const { person } = this.state;  const { username } = this.state;  return (    !isSignInPending() && person ?    <div className="container">      <div className="row">        <div className="col-md-offset-3 col-md-6">          <div className="col-md-12">            <div className="avatar-section">              <img                src={ person.avatarUrl() ? person.avatarUrl() : avatarFallbackImage }                className="img-rounded avatar"                id="avatar-image"              />              <div className="username">                <h1>                  <span id="heading-name">{ person.name() ? person.name()                    : 'Nameless Person' }</span>                  </h1>                <span>{username}</span>                <span>                  &nbsp;|&nbsp;                  <a onClick={ handleSignOut.bind(this) }>(Logout)</a>                </span>              </div>            </div>          </div>          <div className="new-status">            <div className="col-md-12">              <textarea className="input-status"                value={this.state.newStatus}                onChange={e => this.handleNewStatusChange(e)}                placeholder="What's on your mind?"              />            </div>            <div className="col-md-12">              <button                className="btn btn-primary btn-lg"                onClick={e => this.handleNewStatusSubmit(e)}              >                Submit              </button>            </div>          </div>        </div>      </div>    </div> : null  ); }


위의 render() 방법에서 우리 또한 사용자의 Blockstack ID 표시 야. 우리는 사용자 프로필 데이터에서이 추출 해야 합니다. ComponentWillMount() 메서드를 찾아서 사람 속성 아래 username 속성을 추가 합니다.


componentWillMount() {  this.setState({    person: new Person(loadUserData().profile),    username: loadUserData().username  }); }


다음으로, 우리가 우리의 입력된 이벤트를 처리 하기 위해 두 가지 방법을 추가할 것입니다.


handleNewStatusChange(event) {  this.setState({newStatus: event.target.value}) } handleNewStatusSubmit(event) {  this.saveNewStatus(this.state.newStatus)  this.setState({    newStatus: ""  }) }


그리고 우리의 새로운 상태를 저장 하려면 저장 작업을 수행 하는 방법:


saveNewStatus(statusText) {  let statuses = this.state.statuses  let status = {    id: this.state.statusIndex++,    text: statusText.trim(),    created_at: Date.now()  }  statuses.unshift(status)  const options = { encrypt: false }  putFile('statuses.json', JSON.stringify(statuses), options)    .then(() => {      this.setState({        statuses: statuses      })    }) }



이제 수 텍스트 상자에 상태를 입력 하 고 제출 버튼을 눌러 저장 해야 합니다.
전송 버튼을 누르면 아무것도 일이 표시 됩니다. 때문에 우리 상태를 표시 하는 모든 코드를 추가 하지 않았습니다.
상태 표시
Render() 메서드를 다시 이동 하 고 다음 블록 텍스트 입력을 포함 하는 div 요소 바로 아래 추가 버튼을 제출.


<div className="col-md-12 statuses">  {this.state.isLoading && <span>Loading...</span>}  {this.state.statuses.map((status) => (      <div className="status" key={status.id}>        {status.text}      </div>    )  )} </div>


우리 또한 페이지 로드 상태를 가져옵니다, 그래서 새로운 메서드 fetchData()를 호출 하 고 componentDidMount() 메서드에서 호출을 추가할 필요가


componentDidMount() {  this.fetchData() } fetchData() {  this.setState({ isLoading: true })  const options = { decrypt: false }  getFile('statuses.json', options)    .then((file) => {      var statuses = JSON.parse(file || '[]')      this.setState({        person: new Person(loadUserData().profile),        username: loadUserData().username,        statusIndex: statuses.length,        statuses: statuses,      })    })    .finally(() => {      this.setState({ isLoading: false })    }) }


이 시점에서 우리는 기본적인 마이크로 블로깅 애플 리 케이 션 우리가 게시 및 보기 상태를 사용할 수 있다. 그러나, 다른 사용자의 상태를 볼 수 없습니다입니다. 우리는 다음 단계에서 멀티 플레이어 부분에 받을 거 야. 하지만 먼저, 우리의 응용 프로그램에 아주 잠시.
Src/styles/style.css를 열고 기존 스타일을 다음으로 바꿉니다.



/* Globals */ a,a:focus,a:hover{color:#fff;} html,body{height:100%;text-align:center;background-color:#191b22;} body{color:#fff} .hide{display:none;} .landing-heading{font-family:'Lato',Sans-Serif;font-weight:400;} /* Buttons */ .btn{font-family:'Lato',Sans-Serif;padding:0.5625rem 2.5rem;font-size:0.8125rem;font-weight:400;line-height:1.75rem;border-radius:0!important;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-ms-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;} .btn-lg{font-size:1.5rem;padding:0.6875rem 3.4375rem;line-height:2.5rem;} .btn:focus,.btn:active:focus,.btn.active:focus{outline:none;} .btn-primary{color:#fff;border:1px solid #2C96FF;background-color:#2C96FF;} .btn-primary:hover,.btn-primary:focus,.btn-primary:active{color:#fff;border:1px solid #1a6ec0;background-color:#1a6ec0;} /* Avatar */ .avatar{width:100px;height:100px;} .avatar-section{margin-bottom:25px;display:flex;text-align:left;} .username{margin-left:20px;} /* Scaffolding */ .site-wrapper{display:table;width:100%;height:100vh;min-height:100%;} .site-wrapper-inner{display:flex;flex-direction:column;justify-content:center;margin-right:auto;margin-left:auto;width:100%;height:100vh;} .panel-authed{padding:0 0 0 0;} /* Home button */ .btn-home-hello{position:absolute;font-family:'Source Code Pro',monospace;font-size:11px;font-weight:400;color:rgba(255,255,255,0.85);top:15px;left:15px;padding:3px 20px;background-color:rgba(255,255,255,0.15);border-radius:6px;-webkit-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);-moz-box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);box-shadow:0px 0px 20px 0px rgba(0,0,0,0.15);} /* Input */ input, textarea{color:#000;padding:10px;} .input-status{width:100%;height:70px;border-radius:6px;} .new-status{text-align:right;} /* Statuses */ .statuses{padding-top:30px;} .status{margin:15px 0px;padding:20px;background-color:#2e2e2e;border-radius:6px}


다 잘만 된다면, 우리와 끝까지 한다 이런식으로 뭔가:



사용자 프로필 조회
자 이제 우리의 Profile.jsx 다른 사용자의 프로필을 표시 하려면 수정할. 우리가 우리가 우리의 import 문을 이전에 추가 blockstack.js 제공 하는 lookupProfile() 메서드를 사용 해야 합니다. lookupProfile()는 Blockstack id를 조회 하 고 프로필 개체를 반환 합니다 프로필의 단일 매개 변수를 걸립니다.

반응-라우터를 설치: 첫째, 우리가 만들어 줄 게 몇 가지 변화 우리의 애플 리 케이 션의 라우팅 구조를 우리가 http://localhost:8080/other_user.id를 방문 하 여 다른 사용자의 프로필을 볼 수 있도록


npm install --save react-router-dom


Src/index.js를 열고 파일의 맨 추가:


import { BrowserRouter } from 'react-router-dom'


다음 ReactDOM.render() 메서드를 src/index.js에서 변경:

ReactDOM.render((  <BrowserRouter>    <App />  </BrowserRouter> ), document.getElementById('root'));


다음 우리는 다시 src/components/App.jsx에가 고 새로운 경로 추가 해야 합니다. Src/components/App.jsx를 열고 반응-라우터-dom에서 스위치와 경로 구성 요소를 가져옵니다.

import { Switch, Route } from 'react-router-dom'

다음으로, render() 방법에 아래 줄을 찾습니다.

: <Profile handleSignOut={ this.handleSignOut } />


그리고 그것을 다음으로 바꿉니다.

 :  <Switch>    <Route      path='/:username?'      render={        routeProps => <Profile handleSignOut={ this.handleSignOut } {...routeProps} />      }    />  </Switch>


이 경로를 설정 하 고 프로필 조회 사용자 이름으로 사용 될 경로 매개 변수를 캡처합니다.

루트 프로젝트 디렉터리에서 webpack.config.js을 열고 다음 줄을 찾습니다. 우리 또한 우리가 제대로 포함 된 URL 경로 처리할 수 있도록 우리의 시스템용 구성에 규칙을 추가 해야 합니다. 문자입니다. 예를 들어 http://localhost:8080/other_user.id 참고: 생산 애플 리 케이 션, 웹 서버가를 처리 하도록 구성 해야.


historyApiFallback: true,


이 변경:

historyApiFallback: {  disableDotRule: true },

참고: 우리 원의 시작이 적용에 대 한 다시 실행 해야 합니다.
이제 우리 src/components/Profile.jsx 다시 이동 하 고 우리가 로컬 사용자 프로필 또는 다른 사용자의 프로필을 보고 결정 하자 하는 단일 메서드 추가.


isLocal() {  return this.props.match.params.username ? false : true }


다음 우리는 우리의 fetchData() 메서드를 수정할 수 있습니다 다음과 같이:


fetchData() {  this.setState({ isLoading: true })  if (this.isLocal()) {    const options = { decrypt: false }    getFile('statuses.json', options)      .then((file) => {        var statuses = JSON.parse(file || '[]')        this.setState({          person: new Person(loadUserData().profile),          username: loadUserData().username,          statusIndex: statuses.length,          statuses: statuses,        })      })      .finally(() => {        this.setState({ isLoading: false })      })  } else {    const username = this.props.match.params.username    lookupProfile(username)      .then((profile) => {        this.setState({          person: new Person(profile),          username: username        })      })      .catch((error) => {        console.log('could not resolve profile')      })  } }


우리는 먼저 isLocal()을 사용 하 여 로컬 사용자 프로필 또는 다른 사용자의 프로필을 보고 있는 우리를 확인 하. 로컬 사용자 프로필 인 경우 우리 우리 앞에 추가 하는 getFile() 함수를 실행 됩니다. 그렇지 않으면, 우리는 lookupProfile() 메서드를 사용 하 여 사용자 이름에 속하는 프로필을 조회.
참고: https 배포, 기본 Blockstack 코어 API 끝점 이름 조회에 대 한 https를 통해 제공 하는 핵심 API를 가리키도록 변경 되어야 합니다. 그렇지 않으면 이름 조회 혼합된 콘텐츠 차단 브라우저 인해 실패 합니다. 자세한 내용은 Blockstack.js 내용은를 참조 하십시오.
사용자의 상태를 가져오기 위하여 추가 하는 다음 블록을 fetchData() lookupProfile(username) 호출한 후 바로... catch((error) {.} 블록 =>:


const options = { username: username, decrypt: false } getFile('statuses.json', options)  .then((file) => {    var statuses = JSON.parse(file || '[]')    this.setState({      statusIndex: statuses.length,      statuses: statuses    })  })  .catch((error) => {    console.log('could not fetch statuses')  })  .finally(() => {    this.setState({ isLoading: false })  })


그리고 마지막으로, 우리 조건에 따라 로그 아웃 버튼, 상태 입력된 텍스트 상자를 렌더링 하 고 그래서 그들은 다른 사용자의 프로필을 볼 때 표시 되지 않습니다 단추를 제출 해야 합니다. Render() 메서드에서 확인 입력 하 고 로그 아웃 버튼을 배치 하 여 자신의 프로필을 보고 있는 {isLocal() &&...} 상태:

{this.isLocal() &&  <span>    &nbsp;|&nbsp;    <a onClick={ handleSignOut.bind(this) }>(Logout)</a>  </span> } //... {this.isLocal() &&  <div className="new-status">    <div className="col-md-12">      <textarea className="input-status"        value={this.state.newStatus}        onChange={this.handleNewStatusChange}        placeholder="What's on your mind?"      />    </div>    <div className="col-md-12 text-right">      <button        className="btn btn-primary btn-lg"        onClick={this.handleNewStatusSubmit}      >        Submit      </button>    </div>  </div> }


그리고 우리는 완료! 브라우저 프로 파일을 볼 수 http://localhost:8080/your_blockstack.id 가리킵니다. 참고: 등록된 Blockstack ID가을 작동 하도록 해야 합니다.





Sort:  

Congratulations @bitfamily! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 1 year!

Click here to view your Board

Support SteemitBoard's project! Vote for its witness and get one more award!