Monacaのサンプルアプリとして、Instagram風の「フォトシェアアプリデザインテンプレート」が登場しました。洗練されたデザインと滑らかなアニメーションが印象的です。

しかしこのアプリはあくまでテンプレートなので、データはすべてアプリ内部にあるものを参照しています。実際にSNSアプリを開発する際にはサーバサイドの機能が必要になります。写真系SNSの場合は次のような機能がいるでしょう。

  • 認証
  • 写真アップロード
  • コメント/ハート
  • プロフィール
  • フォロー/フォロワー

これらの機能がバックエンドに存在することで、他のユーザと写真を共有したり、お互いをフォローすることができます。すべての機能を自作しても良いのですが、バックエンド機能を一括で提供する専用のクラウドサービスも存在します。私たちの提供するニフクラ mobile backendもその一つです。今回から数回に分けて、このフォトシェアアプリにバックエンド機能を実装してみたいと思います。

まず最初は、認証処理を実装します。

まずはばらす

フォトシェアアプリはOnsen UIで作られています。Onsen UIでは一つのHTMLの中にテンプレートを定義して開発できます。フォトシェアアプリについてもindex.htmlだけですべての処理を行っています。しかし、このままでは開発生産性においてコードの見通しが悪くなりそうです。

そこでテンプレートを切り出して、別のHTMLファイルにしていきます。やり方としては <template> で囲まれた内容を template タグに書かれているidでHTMLファイルにします。例えば <template id="profile.html"> となっていれば、 profile.html というファイルを作成して、<ons-page> 以下の内容をすべて移動します。

今回のフォトシェアアプリについては以下のファイル群になりました。

  • camera.html
  • following-notifications.html
  • home.html
  • notification.html
  • profile.html
  • search.html
  • your-notification.html

タブバーの内容を分ける

ログイン後に表示されるべきタブバーが認証画面に表示されているのは違和感があります。そこで、index.htmlの body タグ内に残った内容をすべて main.html というファイルに移します(main.htmlは新規作成します)。そしてindex.htmlには ons-navigator を追加します。

<ons-navigator swipeable id="nav" page="main.html"></ons-navigator>

こうすることで初期表示は変わりませんが、タブバーがある画面とない画面(これから作ります)を分けやすくなります。

登録/ログインページの作成

未ログイン状態でアプリを開いた際、最初に表示されるのが登録/ログインページです。これは register.html として新規作成します。ページ内容は次のようになります。ユーザ名とパスワードの入力欄があるだけの画面です。ボタンを押した時に login 関数を呼びます(これから作ります)。

<ons-page class="main_pages"  id="register-page">
  <ons-toolbar>
    <div class="center">Register / Login</div>
  </ons-toolbar>

  <div class="content" style="background-color: white !important">

    <div style="padding: 14px 6px 14px 16px;text-align: center;">
      <div class="profile_wrapper">
        <div style="text-align: center; margin-top: 30px;">
          <p>
            <ons-input id="username" modifier="underbar" placeholder="Username" float></ons-input>
          </p>
          <p>
            <ons-input id="password" modifier="underbar" type="password" placeholder="Password" float></ons-input>
          </p>
          <p style="margin-top: 30px;">
            <ons-button onclick="login()">Register / Login</ons-button>
          </p>
        </div>
      </div>
    </div>
  </div>
</ons-page>

JavaScriptファイルの作成

www/js/app.js を新規作成して、 index.html の scriptタグ内にあった内容をすべて移します。そして index.html 内に次のように記述してファイルを読み込みます。

<script src="js/app.js"></script>

ニフクラ mobile backendの初期化

次はニフクラ mobile backend の JavaScript SDK の追加と初期化を行います。手順は省略しますが、ニフクラ mobile backend はここから登録できます。ユーザ登録はGoogleやFacebook、Twitterなどのソーシャルアカウントで可能です。登録するとアプリケーションキーとクライアントキーという二つのキーを取得できます。

MonacaでJavaScript SDKを使う場合は、設定メニューの「JS/CSSコンポーネントの追加と削除」を選択します。
その中にあるテキストボックスに「ncmb」(ニフクラ mobile backendの略です)と入力して検索ボタンを押してください。バージョンはデフォルトのままでインストールを開始し、「ncmb.min.js」にチェックを入れて完了してください。

設定が終わったら、 app.js の中で初期化をします。app.jsの1~3行目に次のように記述してください。

const applicationKey = 'YOUR_APPLICATION_KEY';
const clientKey = 'YOUR_CLIENT_KEY';
const applicationId = 'YOUR_APPLICATION_ID';

YOUR_APPLICATION_KEYYOUR_CLIENT_KEY は、前述のユーザ登録後に表示されるキーに書き換えてください。
また、YOUR_APPLICATION_ID を以下に示すアプリケーションIDに書き換えてください。
アプリケーションIDは、ニフクラ mobile backend のダッシュボードURLに含まれる、applications/ の後ろに続けて表示される英数字です。
https://console.mbaas.nifcloud.com/#/applications/{アプリケーションID}

これでニフクラ mobile backendの初期化が完了です。

認証チェック

認証チェックは次のように行います。 ncmb.User.getCurrentUser() を呼び出して、返却されたデータが空であれば未ログイン状態であるということになります。

const user = ncmb.User.getCurrentUser();
if (!user) {
  // 未ログイン
}

これを使って、初期表示の際に認証状態をチェックします。すでに記述されている document.addEventListener('init', 〜) の処理を以下のように書き換えます。

document.addEventListener('init', function(event) {
  var page = event.target;
  const user = ncmb.User.getCurrentUser();
  if (page.id === 'main') {
    if (!user) {
      // ログインページを表示
      document.querySelector('#nav').pushPage('register.html', {animation: 'fade'});
    }
  }
  if (page.id == "home-page") {
    var stories = page.querySelector('#stories');
    generateStoryBubbles(stories);
  }
});

未ログイン状態だった場合、ons-navigator の pushPage を使って登録/ログイン画面に遷移します。

登録/ログイン処理

前述の通り、認証処理は login 関数内で行います。ここでは簡略化して次のように処理します。

  1. 入力された情報(ユーザID、パスワード)でユーザ登録を実行
  2. 1.に成功したら、自動でログイン処理を実行。成功したらメイン画面に遷移
  3. 1.に失敗したら、既にユーザ登録済みの可能性があるのでログイン処理を実行。成功したらメイン画面に遷移
  4. すべての処理に失敗したらエラー

このように、新規登録とログイン処理を兼ねた処理を行うことにします。以下が登録/ログイン処理ですが、 new ncmb.User() がユーザオブジェクトの作成、 signUpByAccount() がユーザ登録処理、 ncmb.User.login() がログイン処理になります。

// ユーザ登録/ログイン処理です
const login = () => {
  // 入力された情報です
  const userName = document.getElementById('username').value;
  const password = document.getElementById('password').value;
  // ユーザを作成します
  const user = new ncmb.User();
  user
    .set("userName", userName)
    .set("password", password)
    // 登録処理を実行します
    .signUpByAccount()
    .then(() => {
      // 登録に成功したらログイン処理を行います
      return ncmb.User.login(userName, password)
    })
    .catch((err) => {
      // 登録に失敗したらユーザ登録済みの可能性があるため、ログイン処理を行います
      return ncmb.User.login(userName, password)
    })
    .then((user) => {
      // ログイン成功したらメイン画面に遷移します
      document.querySelector('#nav').pushPage('main.html', {animation: 'fade'});
    })
    .catch((err) => {
      // 失敗したらアラートを出します
      ons.notification.alert('Login failed.')
    });
};

ログアウト処理

今回はユーザプロフィール画面でログアウトできるようにします。元々右上はギアアイコンでしたが、今回はここをログアウトアイコンに変更します。内容は profile.html に定義しています。

<div class="right">
  <ons-toolbar-button onclick="logout()"><ons-icon icon="ion-power"></ons-icon></ons-toolbar-button>
</div>

ログアウト処理は app.js の logout 関数内で行っています。ncmb.User.logout() でログアウトを実行します。

// ログアウト処理です
const logout = () => {
  // 確認ダイアログを出します
  ons.notification.confirm({
    message: 'Are you sure?'
  })
  .then((id) => {
    // id == 1 はOKボタンを押した場合です
    // Cancelを押した場合は例外処理を出してPromiseを抜けます
    if (id != 1) {
      throw 1;
    }
    // ログアウト処理
    return ncmb.User.logout();
  })
  .then(() => {
    // 処理完了したら登録/ログイン画面に遷移します
    document.querySelector('#nav').pushPage('register.html', {animation: 'fade'});
  })
  .catch(() => {
    // 確認ダイアログでCancelを選んだ場合
  });
};

ここまでの処理で認証処理が完成しました。ニフクラ mobile backendを使うと既存のアプリに対しても簡単にサーバサイドの処理が実装できるのが分かるかと思います。今回までのソースコードはNCMBMania/photoshare at v0.1にアップロードしてあります。実装時の参考にしてください。

次回以降、写真アップロードやフォローと言った仕組みを作っていきますのでお楽しみに!