Save 37% off PRO during our Black Friday Sale! »

Eight メンション機能の
フロントエンド実装 / Eight Mention Frontend

Bd73c8006f95df876a0dda5c8f43502b?s=47 mokuo
October 22, 2018

Eight メンション機能の
フロントエンド実装 / Eight Mention Frontend

「プラットフォームサービスの成長を支える技術〜Web現場Meetup #4」で発表した際の資料になります。
https://pixta-inc.connpass.com/event/103943/

Bd73c8006f95df876a0dda5c8f43502b?s=128

mokuo

October 22, 2018
Tweet

Transcript

  1. Eight メンション機能の フロントエンド実装 DSOC Development Group ΤϯδχΞ ໦ా༔Ұ࿠ プラットフォームサービスの成⻑を⽀える技術〜 Web現場Meetup

    #4 2018/10/22
  2. ⾃⼰紹介

  3. プロフィール • 名前 : ⽊⽥ 悠⼀郎 • 趣味 : テニス、個⼈開発、ブログ

    • Twitter : @mokuo_ • GitHub : mokuo • Qiita : @mokuo • 個⼈ブログ : blog.mokuo.me
  4. 経歴 • SIer, Rails 受託開発会社などを経験 • 2018年2⽉ Sansan ⼊社 Eight

    事業部配属 • Rails エンジニアとして⼊社したが、気づくと React を書いていた • メンション機能のWebフロントエンド実装を担当 • 2018年6⽉ DSOC に異動 • Rails エンジニアに戻る • GEES(名刺データ化システム)の開発・運⽤をやっています
  5. DSOC について 5 • Data Strategy & Operation Center •

    「データ⽣成から活⽤へ」 • 名刺のデータ化 • 新たな価値 参照 : https://jp.corp-sansan.com/dsoc/about.html
  6. アジェンダ

  7. アジェンダ - Eight 開発環境 - Eight メンション機能とは - Eight メンション機能の設計

    - Eight メンション機能のサーバーサイド - Eight メンション機能のフロントエンド - 使⽤ライブラリ - Eight における実装
  8. Eight 開発環境 8

  9. Eight 開発環境 - サーバーサイド - Ruby on Rails - フロントエンド

    - React + Redux - インフラ - AWS
  10. Eight メンション機能とは 10

  11. Eight メンション機能とは - 投稿をするとき、特定の相⼿をメンションする – Eight ヘルプ 11 ౤ߘྫ ίϝϯτྫ

  12. メンション機能の設計 12

  13. メンション機能の設計 - 設計にあたり、他サービスを調査 13

  14. Twitter - Twitter API ドキュメント - メンション位置情報を保持 14 [ {

    "text": "@jasoncosta @themattharris Hey! Going to be in Frisco in October. Was hoping to have a meeting to talk about @thinkwall if you're around?", "mentions": [ { "user_name": "Jason Costa", ”user_id": 14927800, "indices": [0, 11], "screen_name": "jasoncosta” }, { "user_name": "Matt Harris", "user_id": 777925, "indices": [12, 26], "screen_name": "themattharris” }, { "user_name": "ThinkWall", "user_id": 117426578, "indices": [109, 119], "screen_name": "thinkwall” } ] } ] @jasoncosta @themattharris Hey! Going to be in Frisco in October. Was hoping to have a meeting to talk about @thinkwall if you're around?", දࣔ͢Δࡍʹ૷০
  15. Twitter ⽅式のメリット・デメリット - メリット - テキストを置換する必要がない - デメリット - 投稿を更新する際にメンション位置も更新する必要がある

    15
  16. Slack - Slack API ドキュメント - メンション部分をプレースホルダーとして 保持 16 [

    { "text": " Hey <@U024BE7LH>, did you see my file? ", "mentions": [ { ”user_name": "Jason Costa", ”user_id": 024BE7LH, "screen_name": "jasoncosta” }, ] } ] Hey @jasoncosta, did you see my file? දࣔ͢Δࡍʹஔ׵
  17. Slack ⽅式のメリット・デメリット - メリット - メンション位置を更新する必要がない - デメリット - メンション部分を

    テキスト <=> プレースホルダ で変換・逆変換する必要があ る 17 @jasoncosta ó <@U024BE7LH>
  18. Eight はどうしたか - 投稿を編集できる場合、メンション位置を更新し続けるのは⼤変 - Twitter は投稿を編集できないので、メンション位置を更新する必要がない - プレースホルダーが適していると判断 18

  19. Eight メンション機能のサーバーサイド 19

  20. テーブル定義(イメージ) 20 users - id - name - … posts

    - id - content - … mentions - id - user_id - post_id
  21. Eight メンション機能のフロントエンド 21

  22. 使⽤ライブラリ 22

  23. メンション機能に使⽤したライブラリ - Draft.js - DraftJS Plugins 23

  24. Draft.js とは - React 向けリッチテキストエディタ - 引⽤、箇条書き、コードブロック、太字・・・etc - Facebook 製

    - https://draftjs.org/ 24
  25. DraftJS Plugins とは - Draft.js のプラグイン - 絵⽂字、メンション、ハッシュタグ・・・etc - https://www.draft-js-plugins.com/

    25
  26. Draft.js の概念 - 主な登場⼈物は5⼈ - EditorState - ContentState - ContentBlock

    - CharacterMetadata - Entity - 実態は Immutable.js の Record 26
  27. Entity について - 引⽤、太字、メンションなどをを Entity という概念で扱う。 - CharacterMetadata (1⽂字)ごとに entity

    を持っていて、1以上の数値か null が⼊る。 - 例)⼭⽥太郎 さん - `entity: 1` => メンション 27 editorState.getCurrentContent().getBlockMap().first() .getCharacterList().toJS() => [ {style: [], entity: "1"}, #⼭ {style: [], entity: "1"}, #⽥ {style: [], entity: "1"}, #太 {style: [], entity: "1"}, #郎 {style: [], entity: null}, #さ {style: [], entity: null}, #ん ]
  28. Draft.js と仲良くなるために - Create React App に Draft.js を⼊れて動作検証 28

  29. Eight における実装 29

  30. 実装例 : フィードにメンションを表⽰する 1. サーバーから投稿⽂とメンション情報を取得 2. 投稿⽂をプレーンテキスト、メンション、URLに分類 - オブジェクトの配列を⽣成 3.

    表⽰ - 2. で作った配列をコンポーネントに渡す 30
  31. オブジェクトの配列を⽣成するイメージ 31 # 実際には、text と mentions はサーバーから送られてきます const text =

    ‘<@p[123456]> さん、URLはhttps://example.comです。'; const mentions = fromJS([ { mentionId: 1, user: { id: 123456, name: '⼭⽥ 太郎', }, } ]); const objects = convertToObjects(text, mentions); => [ { type: 'mention', props: { href: '/users/123456' }, body: '⼭⽥ 太郎' }, { type: 'plainText', body: ' さん、URLは' }, { type: 'url' , props: { href: 'https://example.com' }, body: 'https://example.com' }, { type: 'plainText', body: 'です。' } ];
  32. 表⽰部分のイメージ ⼭⽥太郎 さん、URLは https://example.com です。 32 <Message objects={objects} /> =>

    <a href="/users/123456" class="mention">⼭⽥ 太郎</a> <span> さん、URLは</span> <a href="https://example.com">https://example.com</a> <span>です。</span>
  33. 他にも、以下のような機能を実装 - 新規投稿でメンションできる - 投稿編集でメンションを追加・削除できる - コメントでも投稿と同様にメンションできる - コメント返信でメンションされる -

    ⾏動ログの取得 - アプリ通知 33
  34. 反省点 - Slack ⽅式ではなく Twitter ⽅式の⽅がシンプルに実装できたかもしれない - Twitter ⽅式 :

    メンション位置情報を保持 - Slack ⽅式 : プレースホルダーに置換 - 正規表現で毎回置換するのが⼤変 - Draft.js が位置情報を持ってくれていた 34
  35. ご清聴ありがとうございました。 35