Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

mokuo
October 22, 2018

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

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

mokuo

October 22, 2018
Tweet

More Decks by mokuo

Other Decks in Programming

Transcript

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

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

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

    「データ⽣成から活⽤へ」 • 名刺のデータ化 • 新たな価値 参照 : https://jp.corp-sansan.com/dsoc/about.html
  4. アジェンダ - Eight 開発環境 - Eight メンション機能とは - Eight メンション機能の設計

    - Eight メンション機能のサーバーサイド - Eight メンション機能のフロントエンド - 使⽤ライブラリ - Eight における実装
  5. 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?", දࣔ͢Δࡍʹ૷০
  6. 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? දࣔ͢Δࡍʹஔ׵
  7. Slack ⽅式のメリット・デメリット - メリット - メンション位置を更新する必要がない - デメリット - メンション部分を

    テキスト <=> プレースホルダ で変換・逆変換する必要があ る 17 @jasoncosta ó <@U024BE7LH>
  8. テーブル定義(イメージ) 20 users - id - name - … posts

    - id - content - … mentions - id - user_id - post_id
  9. Draft.js の概念 - 主な登場⼈物は5⼈ - EditorState - ContentState - ContentBlock

    - CharacterMetadata - Entity - 実態は Immutable.js の Record 26
  10. 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}, #ん ]
  11. オブジェクトの配列を⽣成するイメージ 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: 'です。' } ];
  12. 表⽰部分のイメージ ⼭⽥太郎 さん、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>
  13. 反省点 - Slack ⽅式ではなく Twitter ⽅式の⽅がシンプルに実装できたかもしれない - Twitter ⽅式 :

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