LoginSignup
11
6

2週間で筋トレ管理SNSをリリースしてみた

Last updated at Posted at 2021-12-04

概要

10月29日(金) 筋肉の日トレーニングの日筋トレ管理SNS「ProTain」 をリリースしました!
ダウンロードはこちらから👇
IOS
Android

もしよければ以下のTweetをリツイートしてください。。

開発チームの紹介

井手翔陽

関西学院大学 商学部3年
2019年 関西学院大学(商学部) に入学
2020年10月 関西学院大学内にてコンピューターサークルTech.Uniを創設
2021年9月 ヤフー株式会社 サマーインターンシップ Yahooプレミアム フロントエンド開発
2021年11月~は楽天グループ株式会社 就業型インターンシップ サーバーサイド開発 (予定)

[技術]
React, Next, Vue, Nuxtを使ったフロントエンド開発
PHP、Laravel、Python、Node.jsを使ったサーバー開発
Flutter, React Nativeを使ったモバイル開発

テザー ナイ ウィン

関西学院大学 理工学部3年
ミャンマー出身、高校卒業後に日本へ留学
2017年 大阪日本語教育センターで日本語の勉強
2019年 関西学院大学(理工学部) に入学
2019年4月~2021年4月 株式会社六角形アルバイト フロントエンド開発
2021年5月~2021年7月 株式会社DataGustoインターン インフラ整備, UI/UX開発, 機械学習スキームなど新機能実装
2021年8月~ Line株式会社(開発3センターTチーム)就業型インターンシップ サーバーサイド開発

開発したアプリの概要

開発したアプリは、筋トレ管理できるスマホアプリケーションです。

ProTainとは

ProTain(プロテイン)は、筋トレ管理SNSです。◇ 筋トレ後にその日のメニューを記録! ◇今日1日の頑張りを全世界に共有! ◇カレンダー機能で自分の成長を可視化! ■ProTainはこんな方にオススメ■ 1. 今日のメニューを記録したい人 洗練された記録機能で部位を分けてその日のメニューを簡単記録。すぐに記録できるから正確なメニューを手軽に記録することを実現。 2.自分の成長を振り返りたい人 過去の自分のウェイトや体型をカレンダーに保存することで振り返る事ができます。 3. 自分の頑張りをシェアしたい人 ProTainerと繋がることで、自分の頑張り・みんなの頑張りを共有し合えます。自分の頑張りを認知してもらうことで自分に打ち勝ち、モチベーションを高く保てます。

使用技術

フロントエンド バックエンド クラウドサービス
Dart Node.js Firebase(mBaaS)
Flutter FireStore Database
Storage
Functions
Authentication
Remote Config

ProTain_previe_done_iphone12a.png

アプリの機能及び実装

①筋トレ管理

✔その日の筋トレメニューを記録!
✔3つのカテゴリーから選択
✔鍛えた箇所をメモ!
ProTain_previe_done_iphone12b.png

②SNS

✔その日のがんばりやつぶやきを世界に共有
✔筋トレ仲間と共に頑張れる
✔フォローしていいねして仲間のトレーニングを刺激にしよう!
ProTain_previe_done_iphone12c.png

③カレンダー

✔1ヶ月カレンダーでトレーニングを振り返ろう
✔毎日のトレーニングをメモ!
✔「先週どこ鍛えたっけ?」を無くします!
ProTain_previe_done_iphone12d.png

開発について

開発メンバー

エンジニア 2名

期間

2週間

技術選定理由

なぜFlutter/Firebaseなのか?

  • 一番速く創れると思ったから。
  • 料金も高くならずに済む
  • 前回のアプリ開発の知見を活かせると感じたから

SNSなので必須機能としては以下のものが最初に挙げられました。

1, ユーザー認証

  • メールアドレス/パスワードでアカウントを作成
  • ログイン機能
  • 既にログインされてる場合はアプリ内に遷移

2, ユーザー管理・プロフィール編集機能

  • プロフィール編集できる
  • ユーザー情報はCloud FireStoreのUsersコレクションで管理

3, CRUD(投稿機能やタイムライン・フォロー/フォロワー・いいね等)

投稿
  • 画像投稿できる
  • 筋トレ/ダイエット/食事の各ジャンル別で投稿できる
  • 筋トレを行ったメニューを投稿できる
タイムライン
  • フォローしているユーザーの投稿を表示
  • ジャンル別に投稿されているタイムラインを表示(フォローしていないユーザーも表示)
フォロー/フォロワー
  • ユーザープロフィールからフォローができる
  • フォロー解除ができる
  • フォロー/フォロワー数はユーザープロフィールに表示
いいね
  • タイムライン上の投稿にいいねができる/いいねを外せる
  • いいねした投稿はユーザープロフィールで確認できる
  • いいね数を表示
  • いいねした時/いいねを外したときにリアルタイムで数字を変更する

上記の実装のほとんどは話し合ってからおよそ6~8時間ほどで完成しました。
(とりあえず簡易的にSNSを完成させて2週間でできそうかを検証。そのためUIなどは何も考えずにTwitterと同じものを再現)

難しかったところ

FireStoreで管理するDB設計(NoSQL設計)
  • 書き込み回数と読み込み回数を考慮する
    • タイムライン表示時のページング機能の実装

以下の記事を参考にしました

ディレクトリ構造

lib
├── Constants // 色やURL、collection名などを簡易的に定義 ※1
│   ├── Constants.dart 
├── Models // 各モデルを作成, シングルトンなどで定義して使い回せるように ※2
│   ├── Activity.dart
│   ├── FirebaseError.dart
│   ├── Menu.dart
│   ├── Tweet.dart
│   └── UserModel.dart
├── Providers // ページング機能実装に必要になったProvider作成
│   └── TweetsProvider.dart
├── Screens //表示する各ページを作成
│   ├── Auth
│   │   ├── AuthScreen.dart
│   │   ├── SignInScreen.dart
│   │   └── SignUpScreen.dart
│   ├── Calender
│   │   └── CalenderScreen.dart
│   ├── FeedScreen.dart
│   ├── Home
│   │   ├── CreateTweetScreen.dart
│   │   └── HomeScreen.dart
│   ├── Notification
│   │   └── NotificationsScreen.dart
│   ├── Profile
│   │   ├── EditProfileScreen.dart
│   │   └── ProfileScreen.dart
│   ├── Report
│   │   └── ReportScreen.dart
│   ├── Search
│   │   └── SearchScreen.dart
│   └── Setting
│       ├── Account
│       │   ├── AccountScreen.dart
│       │   ├── ChangePass.dart
│       │   └── Info.dart
│       ├── Security
│       │   └── SecurityScreen.dart
│       └── SettingScreen.dart
├── Services //Firebaseで使うAPIをまとめたもの ※3
│   ├── DatabaseServices.dart
│   ├── StorageService.dart
│   └── AuthService.dart
├── Utils //便利な関数などを生成
│   ├── Auth
│   │   └── FirebaseError.dart
│   └── Utils.dart
├── Widgets //共通で使えるようなWidgetを作成 
│   ├── AddMenuDialog.dart
│   ├── AppBar.dart
│   ├── Auth
│   │   ├── background_painter.dart
│   │   ├── decoration_function.dart
│   │   ├── sign_in_up_bar.dart
│   │   └── title.dart
│   ├── Drawer.dart
│   ├── FabBottomBar.dart
│   ├── FollowList.dart
│   ├── ImagePreview.dart
│   ├── TimeLine.dart
│   └── TweetContainer.dart
└── main.dart
注釈

コードを一部抜粋したものになります。全てではありません

※1 Constantsディレクトリ

Constants.dart
//共通で使う色を指定
class Palette {
  static const Color red = Color.fromRGBO(221, 17, 17, 1);
  static const Color yellow = Color.fromRGBO(255, 219, 0, 1);
  static const Color darkBlue = Color(0xff092E34);
  static const Color lightBlue = Color(0xff489FB5);
  static const Color darkOrange = Color(0xffCC7700);
}

//FireStoreのコレクションは長いので省略しておく。リファレンスの参照なので命名は~Refで統一
final _fireStore = FirebaseFirestore.instance;
final _fireAuth = FirebaseAuth.instance;

final usersRef = _fireStore.collection('users');

※2 Modelsディレクトリ
https://dart.dev/guides/language/language-tour#constructors

UserModel.dart
class UserModel {
  String id;
  String name;
  String profilePicture;
  String email;
  String bio;
  String coverImage;
  String uid;

  UserModel(
      {this.id,
      this.name,
      this.profilePicture,
      this.email,
      this.bio,
      this.coverImage,
      this.uid});

  // FireStoreからインスタンスを生成
  factory UserModel.fromDoc(DocumentSnapshot doc) {
    return UserModel(
      id: doc.id,
      name: doc['name'],
      email: doc['email'],
      profilePicture: doc['profilePicture'],
      bio: doc['bio'],
      coverImage: doc['coverImage'],
      uid: doc['uid'],
    );
  }
}

※3 Servicesディレクトリ

DatabaseServices.dart
class DatabaseServices { 
  static Future<int> getFollowingNum(String userId) async {
    QuerySnapshot followingSnapshot =
        await followingRef.doc(userId).collection('Following').get();
    return followingSnapshot.docs.length;
  }

  static Future<List<UserModel>> getFollowingUser(String userId) async {
    QuerySnapshot followingSnapshot =
        await followingRef.doc(userId).collection('Following').get();
    List<UserModel> followingUsers = [];

    for (var followingUser in followingSnapshot.docs) {
      await usersRef
          .doc(followingUser.id)
          .get()
          .then((value) => followingUsers.add(UserModel.fromDoc(value)));
    }
    return followingUsers;
  }

  static Future<bool> isFollowingUser(
      String currentUserId, String visitedUserId) async {
    DocumentSnapshot followingDoc = await followersRef
        .doc(visitedUserId)
        .collection('Followers')
        .doc(currentUserId)
        .get();
    return followingDoc.exists;
  }
}

今後の展望

現在DL数は200/DAUは50ほどと少しずつ増えては来ているのでこの調子でユーザー獲得を目指してたくさんの人に使ってもらいたいなと思っています。
また、リプライ機能やサブスク導入とまだまだタスクは残っているので日々アップデートを重ねてよりよいSNSを創っていけたらと思います。
是非、インストールして筋トレ管理をアップデートしてみてください!!
スクリーンショット 2021-12-04 17.34.45.png
スクリーンショット 2021-12-04 17.28.49.png

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6