[PLAY STEEM x PWA] 웹앱 개발 계획

PLAY STEEM 개발자 이타인클럽(@etainclub)입니다.

PLAY STEEM을 웹앱으로 만드는 개발을 하고 있습니다. PLAY STEEM과는 별도의 프로젝트입니다.

  • PLAY STEEM: react native로 만든 안드로이드, 아이폰 앱
  • PLAY STEEM PWA: Flutter로 만들고 있는 웹앱

PWA에 대한 상세한 내용은 이전글을 참고해주세요.
[PLAY STEEM PWA] 포스트 페칭 성공. 그러나..


스팀 블록체인 인터페이스

원래 계획은 dsteem이라는 자바스크립트 라이브러리를 사용하여 스팀 블록체인과 인터페이스 하려고 했습니다.

그런데, dsteem이 최근에 생긴 인터페이스를 지원하지 않는 거 같습니다. 그래서 dsteem은 트랜잭션 사이닝과 같은 필수적인 부분에만 사용하고, 데이터를 가져오는 것은 Flutter 자체 함수를 만들어서 구현하려고 합니다.

Flutter는 dart라는 언어로 코딩하는데요, 이제 좀 익숙해져 갑니다.

  • 데이터 가져오기: 플러터 함수 구현
  • 트랙잭션 사이닝: dsteem 라이브러리 사용

데이터 가져오기

1. 데이터 모델 만들기

스팀 블록에 있는 포스트 데이터를 저장하기 위한 Post 모델 클래스입니다.

class Post {
  // reference
  PostRef? parentRef;
  PostRef postRef;

  // stats
  final DateTime createdAt;
  DateTime? updatedAt;
  int votesCount = 0;
  int resteemCount = 0;
  int commentsCount = 0;
  int? bookmarksCount = 0;
  String payout = '0';
  List<dynamic> voters = [];
  bool? nsfw;
  bool isPromoted = false;

  // post
  final int id;
  final int reputation = 25;
  String title = '';
  String body = '';
  String markdownBody = '';
  String summary = '';
  String image = '';
  final String url;
  //
  String jsonMetadata = '';
  List<String> tags = [];
  int depth = 0;
  int children = 0;

  // user action related
  bool voted = false;
  bool downVoted = false;
  bool? bookmarked = false;
  bool? resteemed = false;
  bool? favorited = false;
  bool? commented = false;
  int? votePercent = 0;

  // comments
  bool isComment = false;

  // community
  String? communityTag = '';
  String? communityTitle = '';

  // constructor
  Post({
    required this.createdAt,
    this.updatedAt,
    required this.postRef,
    required this.isComment,
    required this.id,
    required this.title,
    required this.body,
    required this.url,
  });

  // constructor for json
  factory Post.fromJson(dynamic json) {
    return Post(
        createdAt: DateTime.parse(json['created']),
        updatedAt: DateTime.parse(json['updated']),
        postRef: PostRef(author: json['author'], permlink: json['permlink']),
        id: json['post_id'],
        title: json['title'],
        body: json['body'],
        url: json['url'],
        isComment: false);
  }
}

2. 데이터 가져오기

데이터를 가져오는 부분은 Flutter(정확히는 dart)의 http client를 이용합니다.

  • http client로 복수의 포스팅 데이터를 json으로 가져오기
  • json을 파싱
  • 파싱된 json 데이터를 Post 리스트로 저장
const FETCH_API = 'bridge';
const FETCH_METHOD = 'get_account_posts';
const NUM_FETCH_POSTS = 20;

Future<List<Post>> fetchPosts(
      {String? account,
      required String observer,
      required String sort,
      required int limit,
      String? tag,
      PostRef? startPostRef}) async {
    final body =
        '{"jsonrpc":"2.0", "method":"$FETCH_API.$FETCH_METHOD", "params":{"account":"$account","limit":$limit,"sort":"$sort"}, "id":1}';

    var url = Uri.parse(BASE_URL);
    List<Post> postList = [];

    try {
      final response = await httpClient.post(url, body: body);
      print('response ${response.body}');
      // convert it to model
      final parsedJson = json.decode(response.body);
      print('parsed result: ${parsedJson['result']}');
      parsedJson['result'].forEach((json) {
        final post = Post.fromJson(json);
        postList.add(post);
      });
      return postList;
    } catch (_) {
      print('failed to fetch posts');
    }
    return postList;
  }

파싱하기 전 json 데이터

response {"jsonrpc":"2.0","result":[{"post_id":90348389,"author":"hwan100","permlink":"11-43-am-kst","category":"hive-190865","title":"[11:43 AM KST] \ub2a6\uc7a0\uc73c\ub85c \uc2dc\uc791\ud558\ub294 \ud3c9\uc628\ud55c \uc77c\uc694\uc77c \uc544\uce68","body":"11:43 AM KST\n\n\uad7f\ubaa8\ub2dd \uc2a4\ud300\uc787!! \n\n\ud3c9\ubc94\ud55c \uae30\ubd84\uacfc \ud3c9\ubc94\ud55c \ucee8\ub514\uc158\uc758 \uc77c\uc694\uc77c \uc544\uce68\uc774\ub2e4. \n\n\uc694\uc998 \uae30\ud0c0 \uc5f0\uc2b5\uc744 \uc790\uafb8 \ubbf8\ub8e8\uace0 \ube7c\uba39\uace0 \uc788\ub294\ub370 \n\n\uc624\ub298\uc740 \ud558\ub8e8\uc885\uc77c \ubc00\ub9b0 \uae30\ud0c0 \uc5f0\uc2b5\uc744 \ubd99\uc7a1\uace0 \uc788\uc5b4\uc57c\uaca0\ub2e4. \n\n\uc624\ub298\uc758 \ud560 \uc77c\n\n1. \ubc25 \uba39\uae30 \n2. \ucef4\ud4e8\ud130 \ucc45\uc0c1 \uc815\ub9ac\n3. \uae30\ud0c0 \uc5f0\uc2b5\n4. \ube60\ub978 \ucde8\uce68\n\n\uc990\uac70\uc6b4 \ud558\ub8e8 \n\n\ub108\ubb34 \ub2a6\uc9c0 \uc54a\uac8c \uc77c\ucc0d \uc7a0\ub4dc\ub294 \uc77c\uc694\uc77c \ub418\uae30\ub97c \ubc14\ub780\ub2e4.","json_metadata":{"tags":["kr","hwan100","goodmorningsteemit","steemit","sunday-morning"],"app":"steemit\/0.2","format":"markdown"},"created":"2021-04-11T02:53:54","updated":"2021-04-11T02:54:06","depth":0,"children":0,"net_rshares":0,"is_paidout":false,"payout_at":"2021-04-18T02:53:54","payout":0.0,"pending_payout_value":"0.000 SBD","author_payout_value":"0.000 SBD","curator_payout_value":"0.000 SBD","promoted":"0.000 SBD","replies":[],"active_votes":[],"author_reputation":64.7,"stats":{"hide":false,"gray":false,"total_votes":0,"flag_weight":0.0},"beneficiaries":[],"max_accepted_payout":"1000000.000 SBD","percent_steem_dollars":10000,"url":"\/hive-190865\/@hwan100\/11-43-am-kst","blacklists":[],"community":"hive-190865","community_title":"Good Morning Steemit","author_role":"admin","author_title":"\uc6d4\uae09\uc7c1\uc774\uc758 \uc544\uce68"},{"post_id":90348224,"author":"abidan78","permlink":"papas-locas-hechas-por-abidan78","category":"hive-148497","title":"Papas locas hechas por @abidan78","body":"<center><div class=\"phishy\">Papas Locas\n<\/div><\/center>\n\n<center>\n\n![IMG-20210410-WA0086.jpg](https:\/\/cdn.steemitimages.com\/DQmZsktT1FF3qNms8RS4sD6piFVWgwMC7o9vYa8nDCHFooK\/IMG-20210410-WA0086.jpg)\n<center><sub>foto de @abidan78\/2126Villa de Cura,Aragua-Venezuela.<\/sub><\/center>\n<div class= \"text-justify\">Hola amigos de steemfoods. Hoy sabado. Dia de descanso y compartir en familia. Les traigo esta deliciosa receta. Para compartir en familia y olvidar un poco el estres de la situacion pais. <\/div><br>\n\n<center><div class=\"phishy\">Materiales.\n<\/div><\/center>\n\n\n|Materiales|\n|--------------|\n| 9 Papas. |\n| 200 gramos de Solomo.|\n|200 gramos de milanesa.|\n|Mayones al gusto.|\n|Salsa de tomate al gusto|\n| Mostaza al Gusto|\n|Sal al gusto.|\n\n<center> \n![IMG-20210410-WA0039.jpg](https:\/\/cdn.steemitimages.com\/DQmRAwA5GfADQvBqeZqEM2MVLsNnLT5t5DwsRiytrKC9E5k\/IMG-20210410-WA0039.jpg)\n<\/center>\n<center><sub>foto de @abidan78\/2126Villa de Cura,Aragua-Venezuela.<\/sub><\/center>\n<center><div class=\"phishy\">Paso a paso.\n<\/div><\/center>\n\n\n<div class= \"text-justify\">1er. Paso: Lavamos y pelamos las papas..<\/div><br>\n\n<center>\n![IMG-20210410-WA0042.jpg](https:\/\/cdn.steemitimages.com\/DQmRCCwcRG4mcuCyqx6PBAU8C8mRJ81SLMWBc8p5Myc29dH\/IMG-20210410-WA0042.jpg)\n<\/center>\n<center><sub>foto de @abidan78\/2126Villa de Cura,Aragua-Venezuela.<\/sub><\/center>\n\n<div class= \"text-justify\">2do. Paso: Picamos nuestras papas en tiras y lavamos.<\/div><br>\n\n<center> \n![IMG-20210410-WA0063.jpg](https:\/\/cdn.steemitimages.com\/DQmewTWLm1ohu1hrkLqbcSFVGVgWXxmRCj98CKBsP1jtJXR\/IMG-20210410-WA0063.jpg)\n<center><sub>foto de @abidan78\/2126Villa de Cura,Aragua-Venezuela.<\/sub><\/center>\n![IMG-20210410-WA0043.jpg](https:\/\/cdn.steemitimages.com\/DQmSPXx2TAUSuCWthyfmEU2gJoZgahoxXhc4WYCamouKwjn\/IMG-20210410-WA0043.jpg)\n<\/center>\n<center><sub>foto de @abidan78\/2126Villa de Cura,Aragua-Venezuela.<\/sub><\/center>\n<div class= \"text-justify\">3er. Paso: En un caldero con suficiente aceite fritamos nuestras papas. <\/div><br>\n\n<center> \n![IMG-20210410-WA0052.jpg](https:\/\/cdn.steemitimages.com\/DQmSs375dn5R4KFybbUqUJasChCGzZKmDYaBaLp5nMLhcXN\/IMG-20210410-WA0052.jpg)\n<center><sub>foto de @abidan78\/2126Villa de Cura,Aragua-Venezuela.<\/sub><\/center>\n![IMG-20210410-WA0053.jpg](https:\/\/cdn.steemitimages.com\/DQmZQqDA6EjYdzfWoDvyVAkX5YtaMv1jZ2tq7WyB634kkN6\/IMG-20210410-WA0053.jpg)\n\n<center><sub>foto de @abidan78\/2126Villa de Cura,Aragua-Venezuela.<\/sub><\/center>\n![IMG-20210410-WA0055.jpg](https:\/\/cdn.steemitimages.com\/DQmWVtuBjL76L9DotBQdAYprpvCAwM76zVPYBerTWqu8V5J\/IMG-20210410-WA0055.jpg)\n<center><sub>foto de @abidan78\/2126Villa de Cura,Aragua-Venezuela.<\/sub><\/center>\n![IMG-20210410-WA0069.jpg](https:\/\/cdn.steemitimages.com\/DQmP5ex2oXUQwAsK2pH8gEdjS7nXw9xAzjp81DnAwsZvULT\/IMG-20210410-WA0069.jpg)\n<\/center>\n<center

파싱 후 Post 데이터

image.png

json 데이터가 Post 데이터로 잘 저장되었습니다!

위 화면은 Post 데이터를 이용하여 화면에 뿌린 것이구요!

좋네요!

계획

다음에는 dsteem을 Flutter에서 사용하는 방법을 정리해서 공유하도록 하겠습니다.

Dart 언어는 자바스크립트를 대체하기 위해 만든 언어입니다. C++와 자바스크립트를 혼합한 느낌입니다.
기존에 자바스크립트로 개발된 훌륭한 라이브러리가 많기 때문에, 자바스크립트 라이브러리를 Dart에서 가져와서 쓰는 기능은 매우 유용할 것입니다.

이제 본격적으로 웹앱 개발이 진행될 예정입니다. 많은 관심과 응원 부탁드립니다!

cc.
@steemcurator01
@steemcurator02
@steemcurator03
@steemcurator04
@steemcurator05
@steemcurator06
@steemcurator07
@steemitblog


https://playsteem.app

Sort:  

Carry on playsteem development that's very helpful for user

스팀을 플러터로도 개발 가능하군요. 대박입니다.
저도 이타인님 글을 보면서 플러터 공부해보려고 합니다.
스팀잇앱 만드는 과정과 소스코드를 모두 공유해주셔서 감사합니다.
덕분에 매우 큰 모티베이션이 되었습니다. 🙇‍♂️

안피곤님 돌아오셨군요! 플레이 스팀이라고 리액트 네이티브로 만든게 있는데 안피곤님이 남기신 자료들이 많은 도움이 됐습니다! 감사합니다.

복귀 환영합니다.

환영해주셔서 감사합니다. 😄
깃헙에서 플레이 스팀 소스코드를 봤습니다.
제가 생각했던 기능이 완벽하게 다 구현되어 있어서 정말 놀랐습니다. 이타인클럽님에게 코딩도 배울겸 기여하고 싶어요. ㅎㅎ

제가 많이 배워야죠! 아직 부족한 게 많아요. 버그도 많고. 기여해주시면 정말 좋겠네요~