├── .bowerrc
├── ionic.project
├── .io-config.json
├── www
├── img
│ ├── ionic.png
│ └── logo1.png
├── css
│ └── style.css
├── templates
│ ├── tab-rooms.html
│ ├── tabs.html
│ ├── signup.html
│ ├── login.html
│ └── tab-chat.html
├── index.html
└── js
│ ├── services.js
│ ├── controllers.js
│ └── app.js
├── README.md
├── .gitignore
├── bower.json
├── package.json
├── config.xml
├── scss
└── ionic.app.scss
├── gulpfile.js
└── hooks
├── after_prepare
└── 010_add_platform_class.js
└── README.md
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "www/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/ionic.project:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ionic-firebase",
3 | "app_id": "7b31aa8d"
4 | }
5 |
--------------------------------------------------------------------------------
/.io-config.json:
--------------------------------------------------------------------------------
1 | {"app_id":"7b31aa8d","api_key":"a897f0826a7cd779be176b110a2dc5baaec56b6eb819ab6a"}
--------------------------------------------------------------------------------
/www/img/ionic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mappmechanic/ionic-firebase/HEAD/www/img/ionic.png
--------------------------------------------------------------------------------
/www/img/logo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mappmechanic/ionic-firebase/HEAD/www/img/logo1.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ionic-firebase
2 | Real Time multi person Chat App using Ionic & Firebase
3 |
4 | It uses the AngularFire library to connect to firebase.
5 |
6 | Steps:
7 |
8 | clone this repo
9 | ```bash
10 | cd ./ionic-firebase-master
11 | npm start
12 | ```
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Specifies intentionally untracked files to ignore when using Git
2 | # http://git-scm.com/docs/gitignore
3 |
4 | node_modules/
5 | platforms/
6 | plugins/
7 | ionic.project
8 | .io-config.json
9 | /www/css/ionic.app.css
10 | /www/css/ionic.app.min.css
11 | /www/lib/
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ionic-firebase",
3 | "private": "true",
4 | "devDependencies": {
5 | "ionic": "driftyco/ionic-bower#1.0.0"
6 | },
7 | "dependencies": {
8 | "firebase": "2.4.2",
9 | "angularfire": "0.9.1",
10 | "angular-moment": "0.9.0"
11 | },
12 | "resolutions": {
13 | "firebase": "2.4.2"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/www/css/style.css:
--------------------------------------------------------------------------------
1 | .logo {
2 | display: block;
3 | position: relative;
4 | width: 60%;
5 | margin: 0 auto;
6 | }
7 | .logoText {
8 | text-align: center;
9 | font-size: 28px;
10 | font-family: fantasy;
11 | }
12 | .item-note {
13 | font-size: 10px;
14 | margin-top: -22px;
15 | margin-right: -35px;
16 | }
17 | .textCenter {
18 | text-align: center;
19 | }
--------------------------------------------------------------------------------
/www/templates/tab-rooms.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{room.name}}
7 |
8 |
9 |
10 |
11 | Loading Rooms
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ionic-firebase",
3 | "version": "1.0.0",
4 | "description": "ionic-firebase: An Ionic project",
5 | "dependencies": {
6 | "gulp": "^3.5.6",
7 | "gulp-clean-css": "^2.0.1",
8 | "gulp-concat": "^2.2.0",
9 | "gulp-rename": "^1.2.0",
10 | "gulp-sass": "^2.3.2"
11 | },
12 | "devDependencies": {
13 | "bower": "^1.3.3",
14 | "gulp-util": "^2.2.14",
15 | "shelljs": "^0.3.0"
16 | },
17 | "scripts": {
18 | "postinstall": "bower install && gulp",
19 | "update-deps": "npm update",
20 | "postupdate-deps": "bower update",
21 | "prestart": "npm install",
22 | "start": "ionic serve"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ionic-firebase
4 |
5 | An Ionic Framework and Cordova project.
6 |
7 |
8 | Ionic Framework Team
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/scss/ionic.app.scss:
--------------------------------------------------------------------------------
1 | /*
2 | To customize the look and feel of Ionic, you can override the variables
3 | in ionic's _variables.scss file.
4 |
5 | For example, you might change some of the default colors:
6 |
7 | $light: #fff !default;
8 | $stable: #f8f8f8 !default;
9 | $positive: #387ef5 !default;
10 | $calm: #11c1f3 !default;
11 | $balanced: #33cd5f !default;
12 | $energized: #ffc900 !default;
13 | $assertive: #ef473a !default;
14 | $royal: #886aea !default;
15 | $dark: #444 !default;
16 | */
17 |
18 | // The path for our ionicons font files, relative to the built CSS in www/css
19 | $ionicons-font-path: "../lib/ionic/fonts" !default;
20 |
21 | // Include all of Ionic
22 | @import "www/lib/ionic/scss/ionic";
23 |
24 |
--------------------------------------------------------------------------------
/www/templates/tabs.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/www/templates/signup.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
16 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/www/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 | myChat
7 |
8 |
9 |
10 |
14 |
18 |
21 |
24 |
25 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var gutil = require('gulp-util');
3 | var bower = require('bower');
4 | var concat = require('gulp-concat');
5 | var sass = require('gulp-sass');
6 | var minifyCss = require('gulp-clean-css');
7 | var rename = require('gulp-rename');
8 | var sh = require('shelljs');
9 |
10 | var paths = {
11 | sass: ['./scss/**/*.scss']
12 | };
13 |
14 | gulp.task('default', ['sass']);
15 |
16 | gulp.task('sass', function(done) {
17 | gulp.src('./scss/ionic.app.scss')
18 | .pipe(sass())
19 | .pipe(gulp.dest('./www/css/'))
20 | .pipe(minifyCss({
21 | keepSpecialComments: 0
22 | }))
23 | .pipe(rename({ extname: '.min.css' }))
24 | .pipe(gulp.dest('./www/css/'))
25 | .on('end', done);
26 | });
27 |
28 | gulp.task('watch', function() {
29 | gulp.watch(paths.sass, ['sass']);
30 | });
31 |
32 | gulp.task('install', ['git-check'], function() {
33 | return bower.commands.install()
34 | .on('log', function(data) {
35 | gutil.log('bower', gutil.colors.cyan(data.id), data.message);
36 | });
37 | });
38 |
39 | gulp.task('git-check', function(done) {
40 | if (!sh.which('git')) {
41 | console.log(
42 | ' ' + gutil.colors.red('Git is not installed.'),
43 | '\n Git, the version control system, is required to download Ionic.',
44 | '\n Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
45 | '\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
46 | );
47 | process.exit(1);
48 | }
49 | done();
50 | });
51 |
--------------------------------------------------------------------------------
/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
29 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/www/templates/tab-chat.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
11 |
12 |
13 | Loading Chats
14 |
15 |
16 | No messages in this room. Send message to start.
17 |
18 |
19 | {{chat.from}} :
20 |
21 |
22 | {{chat.message}}
23 |
24 | Delete
25 |
26 |
27 |
28 |
29 |
30 | Please select a room to chat first.
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/www/js/services.js:
--------------------------------------------------------------------------------
1 | angular.module('mychat.services', ['firebase'])
2 | .factory("Auth", ["$firebaseAuth", "$rootScope",
3 | function ($firebaseAuth, $rootScope) {
4 | var ref = new Firebase(firebaseUrl);
5 | return $firebaseAuth(ref);
6 | }])
7 |
8 | .factory('Chats', function ($firebase, Rooms) {
9 |
10 | var selectedRoomId;
11 |
12 | var ref = new Firebase(firebaseUrl);
13 | var chats;
14 |
15 | return {
16 | all: function () {
17 | return chats;
18 | },
19 | remove: function (chat) {
20 | chats.$remove(chat).then(function (ref) {
21 | ref.key() === chat.$id; // true item has been removed
22 | });
23 | },
24 | get: function (chatId) {
25 | for (var i = 0; i < chats.length; i++) {
26 | if (chats[i].id === parseInt(chatId)) {
27 | return chats[i];
28 | }
29 | }
30 | return null;
31 | },
32 | getSelectedRoomName: function () {
33 | var selectedRoom;
34 | if (selectedRoomId && selectedRoomId != null) {
35 | selectedRoom = Rooms.get(selectedRoomId);
36 | if (selectedRoom)
37 | return selectedRoom.name;
38 | else
39 | return null;
40 | } else
41 | return null;
42 | },
43 | selectRoom: function (roomId) {
44 | console.log("selecting the room with id: " + roomId);
45 | selectedRoomId = roomId;
46 | if (!isNaN(roomId)) {
47 | chats = $firebase(ref.child('rooms').child(selectedRoomId).child('chats')).$asArray();
48 | }
49 | },
50 | send: function (from, message) {
51 | console.log("sending message from :" + from.displayName + " & message is " + message);
52 | if (from && message) {
53 | var chatMessage = {
54 | from: from.displayName,
55 | message: message,
56 | createdAt: Firebase.ServerValue.TIMESTAMP
57 | };
58 | chats.$add(chatMessage).then(function (data) {
59 | console.log("message added");
60 | });
61 | }
62 | }
63 | }
64 | })
65 |
66 | /**
67 | * Simple Service which returns Rooms collection as Array from Salesforce & binds to the Scope in Controller
68 | */
69 | .factory('Rooms', function ($firebase) {
70 | // Might use a resource here that returns a JSON array
71 | var ref = new Firebase(firebaseUrl);
72 | var rooms = $firebase(ref.child('rooms')).$asArray();
73 |
74 | return {
75 | all: function () {
76 | return rooms;
77 | },
78 | get: function (roomId) {
79 | // Simple index lookup
80 | return rooms.$getRecord(roomId);
81 | }
82 | }
83 | });
--------------------------------------------------------------------------------
/hooks/after_prepare/010_add_platform_class.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // Add Platform Class
4 | // v1.0
5 | // Automatically adds the platform class to the body tag
6 | // after the `prepare` command. By placing the platform CSS classes
7 | // directly in the HTML built for the platform, it speeds up
8 | // rendering the correct layout/style for the specific platform
9 | // instead of waiting for the JS to figure out the correct classes.
10 |
11 | var fs = require('fs');
12 | var path = require('path');
13 |
14 | var rootdir = process.argv[2];
15 |
16 | function addPlatformBodyTag(indexPath, platform) {
17 | // add the platform class to the body tag
18 | try {
19 | var platformClass = 'platform-' + platform;
20 | var cordovaClass = 'platform-cordova platform-webview';
21 |
22 | var html = fs.readFileSync(indexPath, 'utf8');
23 |
24 | var bodyTag = findBodyTag(html);
25 | if(!bodyTag) return; // no opening body tag, something's wrong
26 |
27 | if(bodyTag.indexOf(platformClass) > -1) return; // already added
28 |
29 | var newBodyTag = bodyTag;
30 |
31 | var classAttr = findClassAttr(bodyTag);
32 | if(classAttr) {
33 | // body tag has existing class attribute, add the classname
34 | var endingQuote = classAttr.substring(classAttr.length-1);
35 | var newClassAttr = classAttr.substring(0, classAttr.length-1);
36 | newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
37 | newBodyTag = bodyTag.replace(classAttr, newClassAttr);
38 |
39 | } else {
40 | // add class attribute to the body tag
41 | newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
42 | }
43 |
44 | html = html.replace(bodyTag, newBodyTag);
45 |
46 | fs.writeFileSync(indexPath, html, 'utf8');
47 |
48 | process.stdout.write('add to body class: ' + platformClass + '\n');
49 | } catch(e) {
50 | process.stdout.write(e);
51 | }
52 | }
53 |
54 | function findBodyTag(html) {
55 | // get the body tag
56 | try{
57 | return html.match(/])(.*?)>/gi)[0];
58 | }catch(e){}
59 | }
60 |
61 | function findClassAttr(bodyTag) {
62 | // get the body tag's class attribute
63 | try{
64 | return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
65 | }catch(e){}
66 | }
67 |
68 | if (rootdir) {
69 |
70 | // go through each of the platform directories that have been prepared
71 | var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
72 |
73 | for(var x=0; x
21 | # Cordova Hooks
22 |
23 | This directory may contain scripts used to customize cordova commands. This
24 | directory used to exist at `.cordova/hooks`, but has now been moved to the
25 | project root. Any scripts you add to these directories will be executed before
26 | and after the commands corresponding to the directory name. Useful for
27 | integrating your own build systems or integrating with version control systems.
28 |
29 | __Remember__: Make your scripts executable.
30 |
31 | ## Hook Directories
32 | The following subdirectories will be used for hooks:
33 |
34 | after_build/
35 | after_compile/
36 | after_docs/
37 | after_emulate/
38 | after_platform_add/
39 | after_platform_rm/
40 | after_platform_ls/
41 | after_plugin_add/
42 | after_plugin_ls/
43 | after_plugin_rm/
44 | after_plugin_search/
45 | after_prepare/
46 | after_run/
47 | after_serve/
48 | before_build/
49 | before_compile/
50 | before_docs/
51 | before_emulate/
52 | before_platform_add/
53 | before_platform_rm/
54 | before_platform_ls/
55 | before_plugin_add/
56 | before_plugin_ls/
57 | before_plugin_rm/
58 | before_plugin_search/
59 | before_prepare/
60 | before_run/
61 | before_serve/
62 | pre_package/ <-- Windows 8 and Windows Phone only.
63 |
64 | ## Script Interface
65 |
66 | All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:
67 |
68 | * CORDOVA_VERSION - The version of the Cordova-CLI.
69 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
70 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
71 | * CORDOVA_HOOK - Path to the hook that is being executed.
72 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
73 |
74 | If a script returns a non-zero exit code, then the parent cordova command will be aborted.
75 |
76 |
77 | ## Writing hooks
78 |
79 | We highly recommend writting your hooks using Node.js so that they are
80 | cross-platform. Some good examples are shown here:
81 |
82 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)
83 |
84 |
--------------------------------------------------------------------------------
/www/js/controllers.js:
--------------------------------------------------------------------------------
1 | angular.module('mychat.controllers', [])
2 |
3 | .controller('LoginCtrl', function ($scope, $ionicModal, $state, $firebaseAuth, $ionicLoading, $rootScope) {
4 | //console.log('Login Controller Initialized');
5 |
6 | var ref = new Firebase($scope.firebaseUrl);
7 | var auth = $firebaseAuth(ref);
8 |
9 | $ionicModal.fromTemplateUrl('templates/signup.html', {
10 | scope: $scope
11 | }).then(function (modal) {
12 | $scope.modal = modal;
13 | });
14 |
15 | $scope.createUser = function (user) {
16 | console.log("Create User Function called");
17 | if (user && user.email && user.password && user.displayname) {
18 | $ionicLoading.show({
19 | template: 'Signing Up...'
20 | });
21 |
22 | auth.$createUser({
23 | email: user.email,
24 | password: user.password
25 | }).then(function (userData) {
26 | alert("User created successfully!");
27 | ref.child("users").child(userData.uid).set({
28 | email: user.email,
29 | displayName: user.displayname
30 | });
31 | $ionicLoading.hide();
32 | $scope.modal.hide();
33 | }).catch(function (error) {
34 | alert("Error: " + error);
35 | $ionicLoading.hide();
36 | });
37 | } else
38 | alert("Please fill all details");
39 | }
40 |
41 | $scope.signIn = function (user) {
42 |
43 | if (user && user.email && user.pwdForLogin) {
44 | $ionicLoading.show({
45 | template: 'Signing In...'
46 | });
47 | auth.$authWithPassword({
48 | email: user.email,
49 | password: user.pwdForLogin
50 | }).then(function (authData) {
51 | console.log("Logged in as:" + authData.uid);
52 | ref.child("users").child(authData.uid).once('value', function (snapshot) {
53 | var val = snapshot.val();
54 | // To Update AngularJS $scope either use $apply or $timeout
55 | $scope.$apply(function () {
56 | $rootScope.displayName = val;
57 | });
58 | });
59 | $ionicLoading.hide();
60 | $state.go('tab.rooms');
61 | }).catch(function (error) {
62 | alert("Authentication failed:" + error.message);
63 | $ionicLoading.hide();
64 | });
65 | } else
66 | alert("Please enter email and password both");
67 | }
68 |
69 | $scope.reSet = function (user) {
70 | if (user.email) {
71 | auth.$sendPasswordResetEmail(user.email).then(function() {
72 | console.log("reset email sent");
73 | alert("reset email sent");
74 | }).catch(function(error) {
75 | alert("reset email failed:" + error.message);
76 | });
77 | } else
78 | alert("Please enter email");
79 | }
80 | })
81 |
82 | .controller('ChatCtrl', function ($scope, Chats, $state) {
83 | //console.log("Chat Controller initialized");
84 |
85 | $scope.IM = {
86 | textMessage: ""
87 | };
88 |
89 | Chats.selectRoom($state.params.roomId);
90 |
91 | var roomName = Chats.getSelectedRoomName();
92 |
93 | // Fetching Chat Records only if a Room is Selected
94 | if (roomName) {
95 | $scope.roomName = " - " + roomName;
96 | $scope.chats = Chats.all();
97 | }
98 |
99 | $scope.sendMessage = function (msg) {
100 | console.log(msg);
101 | Chats.send($scope.displayName, msg);
102 | $scope.IM.textMessage = "";
103 | }
104 |
105 | $scope.remove = function (chat) {
106 | Chats.remove(chat);
107 | }
108 | })
109 |
110 | .controller('RoomsCtrl', function ($scope, Rooms, Chats, $state) {
111 | //console.log("Rooms Controller initialized");
112 | $scope.rooms = Rooms.all();
113 |
114 | $scope.openChatRoom = function (roomId) {
115 | $state.go('tab.chat', {
116 | roomId: roomId
117 | });
118 | }
119 | });
--------------------------------------------------------------------------------
/www/js/app.js:
--------------------------------------------------------------------------------
1 | // MyChat App - Ionic & Firebase Demo
2 |
3 | var firebaseUrl = "https://sizzling-inferno-3944.firebaseio.com";
4 |
5 | function onDeviceReady() {
6 | angular.bootstrap(document, ["mychat"]);
7 | }
8 | //console.log("binding device ready");
9 | // Registering onDeviceReady callback with deviceready event
10 | document.addEventListener("deviceready", onDeviceReady, false);
11 |
12 | // 'mychat.services' is found in services.js
13 | // 'mychat.controllers' is found in controllers.js
14 | angular.module('mychat', ['ionic', 'firebase', 'angularMoment', 'mychat.controllers', 'mychat.services'])
15 |
16 | .run(function ($ionicPlatform, $rootScope, $location, Auth, $ionicLoading) {
17 | $ionicPlatform.ready(function () {
18 | // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
19 | // for form inputs)
20 | if (window.cordova && window.cordova.plugins.Keyboard) {
21 | cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
22 | }
23 | if (window.StatusBar) {
24 | // org.apache.cordova.statusbar required
25 | StatusBar.styleDefault();
26 | }
27 | // To Resolve Bug
28 | ionic.Platform.fullScreen();
29 |
30 | $rootScope.firebaseUrl = firebaseUrl;
31 | $rootScope.displayName = null;
32 |
33 | Auth.$onAuth(function (authData) {
34 | if (authData) {
35 | console.log("Logged in as:", authData.uid);
36 | } else {
37 | console.log("Logged out");
38 | $ionicLoading.hide();
39 | $location.path('/login');
40 | }
41 | });
42 |
43 | $rootScope.logout = function () {
44 | console.log("Logging out from the app");
45 | $ionicLoading.show({
46 | template: 'Logging Out...'
47 | });
48 | Auth.$unauth();
49 | }
50 |
51 |
52 | $rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
53 | // We can catch the error thrown when the $requireAuth promise is rejected
54 | // and redirect the user back to the home page
55 | if (error === "AUTH_REQUIRED") {
56 | $location.path("/login");
57 | }
58 | });
59 | });
60 | })
61 |
62 | .config(function ($stateProvider, $urlRouterProvider) {
63 | console.log("setting config");
64 | // Ionic uses AngularUI Router which uses the concept of states
65 | // Learn more here: https://github.com/angular-ui/ui-router
66 | // Set up the various states which the app can be in.
67 | // Each state's controller can be found in controllers.js
68 | $stateProvider
69 |
70 | // State to represent Login View
71 | .state('login', {
72 | url: "/login",
73 | templateUrl: "templates/login.html",
74 | controller: 'LoginCtrl',
75 | resolve: {
76 | // controller will not be loaded until $waitForAuth resolves
77 | // Auth refers to our $firebaseAuth wrapper in the example above
78 | "currentAuth": ["Auth",
79 | function (Auth) {
80 | // $waitForAuth returns a promise so the resolve waits for it to complete
81 | return Auth.$waitForAuth();
82 | }]
83 | }
84 | })
85 |
86 |
87 | // setup an abstract state for the tabs directive
88 | .state('tab', {
89 | url: "/tab",
90 | abstract: true,
91 | templateUrl: "templates/tabs.html",
92 | resolve: {
93 | // controller will not be loaded until $requireAuth resolves
94 | // Auth refers to our $firebaseAuth wrapper in the example above
95 | "currentAuth": ["Auth",
96 | function (Auth) {
97 | // $requireAuth returns a promise so the resolve waits for it to complete
98 | // If the promise is rejected, it will throw a $stateChangeError (see above)
99 | return Auth.$requireAuth();
100 | }]
101 | }
102 | })
103 |
104 | // Each tab has its own nav history stack:
105 |
106 | .state('tab.rooms', {
107 | url: '/rooms',
108 | views: {
109 | 'tab-rooms': {
110 | templateUrl: 'templates/tab-rooms.html',
111 | controller: 'RoomsCtrl'
112 | }
113 | }
114 | })
115 |
116 | .state('tab.chat', {
117 | url: '/chat/:roomId',
118 | views: {
119 | 'tab-chat': {
120 | templateUrl: 'templates/tab-chat.html',
121 | controller: 'ChatCtrl'
122 | }
123 | }
124 | })
125 |
126 | // if none of the above states are matched, use this as the fallback
127 | $urlRouterProvider.otherwise('/login');
128 |
129 | });
--------------------------------------------------------------------------------