ElmとFirebaseでチャットアプリを写経してみる(2)複数ファイルを1個のファイルにする
ElmとFirebaseでチャットアプリを作成したいシリーズの2回目。前回は、
https://github.com/qnoyxu/chat-room
のコードを実行し、Netlifyにデプロイしてみたのですが、自分ではそのコードを変更することが困難なので、まずは、複数ファイルを1個のファイルにしてみたいと思います。
https://qiita.com/qnoyxu/items/ee479b2b96831907e024
- 1. 今回やりたいこと
- 2. ElmとFirebaseでチャットアプリ目次
- 3. 開発環境
- 4. 新規Elmアプリの作成
- 5. ElmでBulmaを使用するための準備
- 6. Firebaseで新規プロジェクトの作成
- 7. index.htmlの編集
- 8. src/Main.elmの新規作成
- 9. SCSS, CSS関連のコードを消す
- 10. Bulmaで少し見栄えを変更する(1)
- 11. 一番下まで自動スクロール
- 12. Browser.Navigationを利用する
- 13. linuss/smooth-scrollパッケージを試してみる
- 14. Bulmaで少し見栄えを変更する(2)
- 15. Netlifyにデプロイ
- 16. ソースコードとDEMOサイト
今回やりたいこと
- https://github.com/qnoyxu/chat-room の複数ファイルを1個のファイルにする
- Bulmaを利用してデザインを少し変更してみる
ソースコード
(index.htmlの55行目のFirebaseのアドレスはご自身のものを入力してください。)
https://github.com/adash333/elm-firebase-chat2
DEMOサイト
https://romantic-noyce-862b75.netlify.com/
ElmとFirebaseでチャットアプリ目次
開発環境
Windows 10 Pro
Chrome
VisualStudioCode 1.32.3
git version 2.20.1.windows.1
nvm 1.1.7
node 10.2.0
npm 6.4.1
elm 0.19.0-bugfix6
elm-format 0.8.1
VisualStudioCodeの拡張機能でelmをインストールして、settings.jsonに以下のようにelmを設定。
(『Alt + Shift + F』と『Ctrl + S』を使用。)
"[elm]": {
"editor.formatOnSave": true
},
新規Elmアプリの作成
C:/elm/ フォルダに、elm-bulma-hamburger/ フォルダを作成し、VisualStudioCodeで開き、Ctrl+@でコマンドプロンプトを開き、以下を入力します。
途中で何か聞かれたらEnterを押します。
elm/json, elm/random, alex-tan/elm-dialog パッケージもインストールしておきます。
elm init
elm install elm/json
elm install elm/random
elm install alex-tan/elm-dialog
参考: https://github.com/qnoyxu/chat-room/blob/master/elm.json
参考2: https://package.elm-lang.org/packages/alex-tan/elm-dialog/latest/
ElmでBulmaを使用するための準備
Browser.documentからBulmaを使用するための以下の2つのファイル(index.html, .gitignore, netlify.toml)をコピペします。
Firebaseで新規プロジェクトの作成
チャット内容を保存するサーバとして、Firebaseアプリを新規作成します。詳細については、こちらを参考にしていただけますと幸いです。
- https://console.firebase.google.com にGoogleアカウントでログイン
- 新規プロジェクト作成
- Project Overview > 「開始するにはアプリを追加してください」のすぐ上の、「</>」をクリック
- 「ウェブアプリに Firebase を追加」画面が出てくるので、中身をメモ帳などにコピーしておく(後で、index.htmlにペーストします)
- Authentication > ログイン方法 > Google をクリックして、Google認証を「有効にする」をONにして保存
- Authentication > ログイン方法 の画面の下の方へ行き、承認済みドメイン のところに localhostが入っていることを確認する。(本番環境にデプロイする場合は、そのドメインを追加する。)
Project Overview
+アプリを追加
Firebase database の 画面に従って入力していくと、
var firebaseConfig = {
の画面が出てくるので、
databaseURL: “https://<YOUR-APPLICATION>.firebaseio.com”,
のところのアドレスをコピーしておきます。
注:”https://<YOUR-APPLICATION>.firebaseio.com” のところは、それぞれの人によって変わります。
なお、セキュリティ的にかなり微妙ですが、今回は、Databaseのルールの設定を、以下のようにしておきます。
{
"rules": {
".read": true,
".write": true
}す
}
index.htmlの編集
写経元サイトの
src/index.html
src/index.js
をコピペします。
参考: http://i-doctor.sakura.ne.jp/font/?p=38262
- firebaseを使用できるようにする
- Elmへportなどで、Firebaseとの通信を行えるようにする
ただし、
const config = {databaseURL: "https://(ここにご自身のFirebaseのURLを記載してください).firebaseio.com"};
のところは、ご自身のFirebaseアプリのURLを記載してください。
src/Main.elmの新規作成
src/Main.elm を新規作成し、引き続き、写経元サイトの
https://github.com/qnoyxu/chat-room/blob/master/src/Main.elm からコピーしていきます。
次に、
Model.elm
をここにコピーします。 init の部分を統合しました。
次に、
Update.elm
をコピーします。UPDATEはそのまま、Main.elmにコピペしました。
次に、
View.elm と Ports.elm
をここにコピーします。
このとき、一番上の行の
module Main exposing (main)
の前に、port を加えて、
port module Main exposing (main)
にしておきます。
SCSS, CSS関連のコードを消す
scssは苦手なので、SCSS, CSS関連のコードを手作業で消していきます。(大丈夫だろうか、、、)
あと、
map
を
List.map
に書き換えたり、
object を Json.Encode.object に書き換えたりして、エラーを減らしていきました。
ここで一度、elm-liveで開発サーバで表示してみます。
elm-live src/Main.elm --open -- --output=main.js
CSSをすべて削除したので見栄えはむちゃくちゃですが、一応、Firebaseからデータは取ってこれているようです。
右上の方で、名前”NoCSSMan”を入力して OK を押し、左下の方でチャットコメントを入力して Send を押すと、たしかにチャットコメントも反映されました。
次は、見栄えをなんとかしてみたいです。
Bulmaで少し見栄えを変更する(1)
こちらのサイトを参考にして、少し見栄えを変更してみます。(参考2:Bulmaで画像)
さらに、HTML to ELM を参考にして、書き換えてみます。
ヘッダーの部分を追加
nav [ class "navbar has-background-info is-fixed-top" ]
[ div [ class "navbar-brand" ]
[ a [ class "navbar-item has-text-white", href "#" ]
[ text "Elm Firebase Bulma Chat" ]
]
]
フッターの部分を編集
(変更前)
viewForm : Message -> Html Msg
viewForm message =
Html.form [ onSubmit Submit ]
[ textarea [ placeholder "Message", wrap "hard", value message, onInput ChangeMessage ] []
, button
[ class "btn btn-success"
, disabled <| String.isEmpty <| String.trim message
]
[ text "send" ]
]
(変更後)
viewForm : Message -> Html Msg
viewForm message =
section [ class "section" ]
[ div [ class "container" ]
[ div [ class "field has-addons" ]
[ div [ class "control is-expanded" ]
[ input [ class "input", placeholder "Message", type_ "text", value message, onInput ChangeMessage ]
[]
]
, div [ class "control" ]
[ a [ class "button is-info", onClick Submit, disabled <| String.isEmpty <| String.trim message ]
[ text "Send" ]
]
]
]
]
elm-live src/Main.elm --open -- --output=main.js
いらすとやから、画像を2つダウンロードして、img/ フォルダに保存します。
https://codesandbox.io/s/divine-sky-z2tnu で見栄えを少し練習してから、HTML to Elmを用いて、VIEWを変更してみます。
index.html の</head>のすぐ上に以下を挿入します。
<link
rel="stylesheet"
href="styles.css"
/>
styles.css の新規作成
.media-body {
padding: 5px 10px;
background-color: #98fb98;
border-radius: 6px;
font-size: 12px;
color: #555;
left: 10%;
right: 10%;
}
VIEWを作るのが結構ストレスです。とりあえず、今のところ、全員くまさんのアイコンで、コメントの位置も右側としておきます。
一番下まで自動スクロール
よくわからないのですが、自動的に一番下まですくろーるしてくれなくなってしまっていますので、自動スクロールされるようにしたいと思います。
写経元のコードを見てみると、Browser.Domの、
- getViewportOf 関数
- setViewportOf 関数
について調べる必要がありそうです。
jumpToBottom "history"
jumpToBottom : String -> Cmd Msg
jumpToBottom id =
Dom.getViewportOf id
|> Task.andThen (\info -> Dom.setViewportOf id 0 info.scene.height)
|> Task.attempt (\_ -> NoOp)
https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom
https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom#setViewportOf
https://qiita.com/uzimaru0000/items/e92e672ab06d77389641
@uzimaru0000
2018年12月19日に更新
任意のイベントデータを含んだメッセージを作る方法とBrowser.Domについて
https://qiita.com/hibohiboo/items/f40315c34d921fba82f0
@hibohiboo
2019年03月22日に更新
Elmでページ内ジャンプをしたメモ
いろいろ試してみましたが、どうしても自動スクロールできません。
https://qiita.com/hibohiboo/items/f40315c34d921fba82f0
の、
「setViewPortOf は、IDで指定した スクロール可能な 要素を任意の位置にスクロールするものであって、スクロール可能な要素に 含まれる要素 をIDで指定してその要素のところまでスクロールさせるものではないです。」
の文面はわかった(つもり)のですが、じゃあ、どうやってやればよいのか、どうしてもわかりません。。。
elm-lang/Navigationは、Elm0.18までのパッケージなのか、私のelm0.19の環境ではインストールできず、Navigation.load 関数を用いることはできませんでした。
挫折か?、、、
今のところのコード(一部)は以下のようにしているのですが、どうしても、自動スクロールできませんでした。。。
elm-live src/Main.elm --open -- --output=main.js
MAIN, SUBSCRIPTIONS, とPORT
UPDATE
VIEW
Browser.Navigationを利用する
なんか勘違いしていたみたいで、以下のimportはできました。
import Browser.Navigation as Nav
https://package.elm-lang.org/packages/elm/browser/latest/Browser-Navigation
しかし、
jumpToBottom “bottom"
のところを、
Nav.load “bottom"
や
Nav.load “index.html#bottom"
にしても、両方とも一番下まで自動スクロールしてくれませんでした。がっくし。。。
linuss/smooth-scrollパッケージを試してみる
linuss/smooth-scrollパッケージを試してみます。
参考:https://package.elm-lang.org/packages/linuss/smooth-scroll/latest/
Ellieで試してみます。
参考2:https://ellie-app.com/5Q6J4RdVfkca1
これをもとに、できるでしょうか、、、
パッケージのインストール
elm install linuss/smooth-scroll
elm-live src/Main.elm --open -- --output=main.js
SmoothScroll と Task をimport
import SmoothScroll exposing (scrollTo)
import Task exposing (Task)
type Msg に SmoothScroll String と NoOpを追加
(今回はもともとNoOpがあったので、SmoothScroll String のみを追加しました。)
type Msg
= NoOp
| SmoothScroll String
update msg modelに以下を追加します。
update msg model =
case msg of
NoOp ->
( model, Cmd.none )
SmoothScroll id ->
( model, Task.attempt (always NoOp) (scrollTo id) )
NewMessage value ->
case decodeMessage value of
Ok form ->
のところの、
jumpToBottom "bottom"
のところを、
Task.attempt (always NoOp) (scrollTo "bottom")
に変更します。
(VIEWのところで、一番下のコメント入力欄のところを div [ Html.Attributes.id “bottom" ] [ viewForm model.message ] として、<div id="bottom">となるようにしています。)
(最初、 ここの部分に、SmoothScroll “bottom" と書いて、『型が違うよ!』と怒られてました。)
これでやっと、FirebaseからチャットのリストをとってきてDecodeが終了した時点で、一番下まで自動スクロールしてくれるようになりました。ふう。
今度、 時間のあるときに
https://github.com/linuss/smooth-scroll
のソースコードを読んでみたいです。
https://github.com/linuss/smooth-scroll/blob/master/src/SmoothScroll.elm
コードの一部は以下のようになっており、やはり、
Dom.setViewport
Dom.getViewport
を用いているようです。読んでもわかりませんが、、、
scrollTo : String -> Task Dom.Error (List ())
scrollTo =
scrollToWithOptions defaultConfig
scrollToWithOptions : Config -> String -> Task Dom.Error (List ())
scrollToWithOptions config id =
let
tasks from to =
List.map (Dom.setViewport 0)
(animationSteps config.speed config.easing from (to - toFloat config.offset))
|> Task.sequence
in
Task.map2 Tuple.pair Dom.getViewport (Dom.getElement id)
|> Task.andThen (\( { viewport }, { element } ) -> tasks viewport.y element.y)
Bulmaで少し見栄えを変更する(2)
コメントリストの表示を、発言者が自分の場合と他人の場合で、絵を分けてみたいと思います。(他人は全員同じくまさんになってしまいますが、今回はこれ以上つっこまないことにします。)
(変更前)
[ p [ class "image is-64x64" ]
[ img [ class "is-rounded", src "img/kuma.png" ] []
]
]
(変更後)
[ p [ class "image is-64x64" ]
[ img
[ class "is-rounded"
, src
(if messageClass == "self" then
"img/usagi.png"
else
"img/kuma.png"
)
]
[]
]
]
さらに、ぐちゃぐちゃやって、以下のようになりました。本当はCSSの float を使うべきだとは思うのですが、よくわからないので、ぐちゃぐちゃなコードですが、以下のような感じになりました。これ以上は突っ込まないことにします。
Ctrl+C => y + Enterで開発サーバを停止し、以下を入力します。
git add .
git commit -m "self image to usagi"
git push
Netlifyにデプロイ
ターミナル画面で以下を入力して、production用のmain.jsを作成します。(今回はUglify.jsは無視します。)
elm make src/Main.elm --output=main.js --optimize
以下を入力して、GitHub(またはBitBucket)にpushします。
git add .
git commit -m "elm make"
git push
https://www.netlify.com/ にログインして、上記GitHub(またはBitBucket)のリポジトリを選択して、デプロイします。設定欄は空白のままです。
デプロイできたようです。
https://romantic-noyce-862b75.netlify.com/
自分はウサギ、自分以外はみんなクマですが、まあ、気にしないことにします。
ソースコードとDEMOサイト
ソースコード
(index.htmlの55行目のFirebaseのアドレスはご自身のものを入力してください。)
https://github.com/adash333/elm-firebase-chat2
DEMOサイト
https://romantic-noyce-862b75.netlify.com/
ディスカッション
コメント一覧
まだ、コメントがありません