├── .firebaserc ├── .gitignore ├── README.md ├── angular.json ├── browserslist ├── capacitor.config.json ├── e2e ├── protractor.conf.js ├── src │ ├── app.e2e-spec.ts │ └── app.po.ts └── tsconfig.json ├── firebase.json ├── ionic-v3 ├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── config.xml ├── ionic.config.json ├── package-lock.json ├── package.json ├── resources │ ├── README.md │ ├── android │ │ ├── icon │ │ │ ├── drawable-hdpi-icon.png │ │ │ ├── drawable-ldpi-icon.png │ │ │ ├── drawable-mdpi-icon.png │ │ │ ├── drawable-xhdpi-icon.png │ │ │ ├── drawable-xxhdpi-icon.png │ │ │ └── drawable-xxxhdpi-icon.png │ │ └── splash │ │ │ ├── drawable-land-hdpi-screen.png │ │ │ ├── drawable-land-ldpi-screen.png │ │ │ ├── drawable-land-mdpi-screen.png │ │ │ ├── drawable-land-xhdpi-screen.png │ │ │ ├── drawable-land-xxhdpi-screen.png │ │ │ ├── drawable-land-xxxhdpi-screen.png │ │ │ ├── drawable-port-hdpi-screen.png │ │ │ ├── drawable-port-ldpi-screen.png │ │ │ ├── drawable-port-mdpi-screen.png │ │ │ ├── drawable-port-xhdpi-screen.png │ │ │ ├── drawable-port-xxhdpi-screen.png │ │ │ └── drawable-port-xxxhdpi-screen.png │ ├── icon.png │ ├── icon.png.md5 │ ├── ios │ │ ├── icon │ │ │ ├── icon-1024.png │ │ │ ├── icon-40.png │ │ │ ├── icon-40@2x.png │ │ │ ├── icon-40@3x.png │ │ │ ├── icon-50.png │ │ │ ├── icon-50@2x.png │ │ │ ├── icon-60.png │ │ │ ├── icon-60@2x.png │ │ │ ├── icon-60@3x.png │ │ │ ├── icon-72.png │ │ │ ├── icon-72@2x.png │ │ │ ├── icon-76.png │ │ │ ├── icon-76@2x.png │ │ │ ├── icon-83.5@2x.png │ │ │ ├── icon-small.png │ │ │ ├── icon-small@2x.png │ │ │ ├── icon-small@3x.png │ │ │ ├── icon.png │ │ │ └── icon@2x.png │ │ └── splash │ │ │ ├── Default-568h@2x~iphone.png │ │ │ ├── Default-667h.png │ │ │ ├── Default-736h.png │ │ │ ├── Default-Landscape-736h.png │ │ │ ├── Default-Landscape@2x~ipad.png │ │ │ ├── Default-Landscape@~ipadpro.png │ │ │ ├── Default-Landscape~ipad.png │ │ │ ├── Default-Portrait@2x~ipad.png │ │ │ ├── Default-Portrait@~ipadpro.png │ │ │ ├── Default-Portrait~ipad.png │ │ │ ├── Default@2x~iphone.png │ │ │ ├── Default@2x~universal~anyany.png │ │ │ └── Default~iphone.png │ ├── splash.png │ └── splash.png.md5 ├── src │ ├── app │ │ ├── app.component.ts │ │ ├── app.html │ │ ├── app.module.ts │ │ ├── app.scss │ │ └── main.ts │ ├── assets │ │ ├── icon │ │ │ └── favicon.ico │ │ └── imgs │ │ │ └── logo.png │ ├── environment │ │ └── environment.ts │ ├── index.html │ ├── manifest.json │ ├── pages │ │ ├── core │ │ │ ├── auth.service.ts │ │ │ ├── user.model.ts │ │ │ └── user.service.ts │ │ ├── login │ │ │ ├── login.html │ │ │ ├── login.scss │ │ │ └── login.ts │ │ ├── register │ │ │ ├── register.html │ │ │ ├── register.scss │ │ │ └── register.ts │ │ └── user │ │ │ ├── user.html │ │ │ ├── user.scss │ │ │ └── user.ts │ ├── service-worker.js │ └── theme │ │ ├── commons.scss │ │ └── variables.scss ├── tsconfig.json └── tslint.json ├── ionic.config.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── src ├── app │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── firebase-auth.service.ts │ ├── profile │ │ ├── profile.model.ts │ │ ├── profile.module.ts │ │ ├── profile.page.html │ │ ├── profile.page.scss │ │ ├── profile.page.spec.ts │ │ ├── profile.page.ts │ │ └── profile.resolver.ts │ ├── sign-in │ │ ├── sign-in.module.ts │ │ ├── sign-in.page.html │ │ ├── sign-in.page.scss │ │ ├── sign-in.page.spec.ts │ │ └── sign-in.page.ts │ └── sign-up │ │ ├── sign-up.module.ts │ │ ├── sign-up.page.html │ │ ├── sign-up.page.scss │ │ ├── sign-up.page.spec.ts │ │ └── sign-up.page.ts ├── assets │ ├── icon │ │ └── favicon.png │ └── shapes.svg ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── global.scss ├── index.html ├── main.ts ├── polyfills.ts ├── test.ts ├── theme │ └── variables.scss └── zone-flags.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json └── tslint.json /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "targets": { 3 | "ionic5-firebase-authentication": { 4 | "hosting": { 5 | "app": [ 6 | "ionic5-firebase-authentication" 7 | ] 8 | } 9 | } 10 | }, 11 | "projects": { 12 | "demo": "ionic5-firebase-authentication" 13 | } 14 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Specifies intentionally untracked files to ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | *~ 5 | *.sw[mnpcod] 6 | .tmp 7 | *.tmp 8 | *.tmp.* 9 | *.sublime-project 10 | *.sublime-workspace 11 | .DS_Store 12 | Thumbs.db 13 | UserInterfaceState.xcuserstate 14 | $RECYCLE.BIN/ 15 | 16 | *.log 17 | log.txt 18 | npm-debug.log* 19 | 20 | /.idea 21 | /.ionic 22 | /.sass-cache 23 | /.sourcemaps 24 | /.versions 25 | /.vscode 26 | /coverage 27 | /dist 28 | /node_modules 29 | /platforms 30 | /plugins 31 | /www 32 | 33 | .firebase 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ionic Firebase Authentication 2 | Enjoy this free Ionic 5 Firebase demo app and save tons of hours of work! 3 | 4 |
5 | 6 | 7 | 8 |
9 | 10 | ## About this ionic demo 11 | This repo is the code of an Ionic 5 starter app that we created as part of the post: **[Ionic Firebase Authentication Tutorial](https://ionicthemes.com/tutorials/about/firebase-authentication-in-ionic-framework-apps). In this post we explain how to perform Social Sign In with Firebase from an Ionic application.** 12 | 13 | Most apps need to know the identity of the user who is using it. Knowing a user's identity allows an app to securely save user data in the cloud and provide a personalized experience across all of the user's devices. 14 | 15 | In this Ionic + Firebase tutorial you will learn how to create an Ionic Framework Application with Firebase Authentication. We will show you how to configure both the Firebase and the Ionic 5 App to enable authentication with social providers such as Google, Facebook and Twitter and also with Email and Password. 16 | 17 | As an example we built this Ionic Framework application that allows users to log in and log out using all of the above mentioned authentication options. Once they log in, they will see a profile page with their basic profile info taken from the authentication provider. 18 | 19 | Read the complete post in https://ionicthemes.com/tutorials/about/firebase-authentication-in-ionic-framework-apps. 20 | 21 | ### Ionic Firebase Starter 22 | This repo is a simple ionic 5 starter app with three pages: 23 | - Sign In 24 | - Sign Up 25 | - Profile 26 | 27 | Find more Ionic tutorials and starter apps in https://ionicthemes.com 28 | 29 | ### Demo 30 | - [Online demo](https://ionic5-firebase-authentication.web.app) 31 | 32 | ## Install this Ionic 5 Firebase App 33 | ``` 34 | npm install 35 | ``` 36 | ### Browse the app 37 | ``` 38 | ionic serve 39 | ``` 40 | 41 | ### Get a premium Ionic 5 Starter App with Firebase Integration 42 | If you want a ready-made example of how to use Firebase Authentication in Ionic 5 with Capacitor configurations for iOS and Android, check [Ionic 5 Full Starter App PRO](https://ionicthemes.com/product/ionic5-full-starter-app-pro-version). We spent many hours configuring and testing everything so that you don't have to. 43 | 44 | This template has more than 100 carefully designed views and components, it will help you grasp the best practices and new concepts of Ionic 5. 45 | 46 | It also includes a very complete integration with Firebase which includes: 47 | - Firebase Authentication with different providers: 48 | - Facebook sign in 49 | - Twitter sign in 50 | - Google sign in 51 | - Email/Password sign in 52 | - This implementation works in all environments: web, PWA, mobile apps with Capacitor. 53 | - Firebase CRUD 54 | - Firebase queries 55 | 56 | 57 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "defaultProject": "app", 5 | "newProjectRoot": "projects", 6 | "projects": { 7 | "app": { 8 | "root": "", 9 | "sourceRoot": "src", 10 | "projectType": "application", 11 | "prefix": "app", 12 | "schematics": {}, 13 | "architect": { 14 | "build": { 15 | "builder": "@angular-devkit/build-angular:browser", 16 | "options": { 17 | "outputPath": "www", 18 | "index": "src/index.html", 19 | "main": "src/main.ts", 20 | "polyfills": "src/polyfills.ts", 21 | "tsConfig": "tsconfig.app.json", 22 | "assets": [ 23 | { 24 | "glob": "**/*", 25 | "input": "src/assets", 26 | "output": "assets" 27 | }, 28 | { 29 | "glob": "**/*.svg", 30 | "input": "node_modules/ionicons/dist/ionicons/svg", 31 | "output": "./svg" 32 | } 33 | ], 34 | "styles": [ 35 | { 36 | "input": "src/theme/variables.scss" 37 | }, 38 | { 39 | "input": "src/global.scss" 40 | } 41 | ], 42 | "scripts": [] 43 | }, 44 | "configurations": { 45 | "production": { 46 | "fileReplacements": [ 47 | { 48 | "replace": "src/environments/environment.ts", 49 | "with": "src/environments/environment.prod.ts" 50 | } 51 | ], 52 | "optimization": true, 53 | "outputHashing": "all", 54 | "sourceMap": false, 55 | "extractCss": true, 56 | "namedChunks": false, 57 | "aot": true, 58 | "extractLicenses": true, 59 | "vendorChunk": false, 60 | "buildOptimizer": true, 61 | "budgets": [ 62 | { 63 | "type": "initial", 64 | "maximumWarning": "2mb", 65 | "maximumError": "5mb" 66 | } 67 | ] 68 | }, 69 | "ci": { 70 | "progress": false 71 | } 72 | } 73 | }, 74 | "serve": { 75 | "builder": "@angular-devkit/build-angular:dev-server", 76 | "options": { 77 | "browserTarget": "app:build" 78 | }, 79 | "configurations": { 80 | "production": { 81 | "browserTarget": "app:build:production" 82 | }, 83 | "ci": { 84 | "progress": false 85 | } 86 | } 87 | }, 88 | "extract-i18n": { 89 | "builder": "@angular-devkit/build-angular:extract-i18n", 90 | "options": { 91 | "browserTarget": "app:build" 92 | } 93 | }, 94 | "test": { 95 | "builder": "@angular-devkit/build-angular:karma", 96 | "options": { 97 | "main": "src/test.ts", 98 | "polyfills": "src/polyfills.ts", 99 | "tsConfig": "tsconfig.spec.json", 100 | "karmaConfig": "karma.conf.js", 101 | "styles": [], 102 | "scripts": [], 103 | "assets": [ 104 | { 105 | "glob": "favicon.ico", 106 | "input": "src/", 107 | "output": "/" 108 | }, 109 | { 110 | "glob": "**/*", 111 | "input": "src/assets", 112 | "output": "/assets" 113 | } 114 | ] 115 | }, 116 | "configurations": { 117 | "ci": { 118 | "progress": false, 119 | "watch": false 120 | } 121 | } 122 | }, 123 | "lint": { 124 | "builder": "@angular-devkit/build-angular:tslint", 125 | "options": { 126 | "tsConfig": [ 127 | "tsconfig.app.json", 128 | "tsconfig.spec.json", 129 | "e2e/tsconfig.json" 130 | ], 131 | "exclude": [ 132 | "**/node_modules/**" 133 | ] 134 | } 135 | }, 136 | "e2e": { 137 | "builder": "@angular-devkit/build-angular:protractor", 138 | "options": { 139 | "protractorConfig": "e2e/protractor.conf.js", 140 | "devServerTarget": "app:serve" 141 | }, 142 | "configurations": { 143 | "production": { 144 | "devServerTarget": "app:serve:production" 145 | }, 146 | "ci": { 147 | "devServerTarget": "app:serve:ci" 148 | } 149 | } 150 | }, 151 | "ionic-cordova-build": { 152 | "builder": "@ionic/angular-toolkit:cordova-build", 153 | "options": { 154 | "browserTarget": "app:build" 155 | }, 156 | "configurations": { 157 | "production": { 158 | "browserTarget": "app:build:production" 159 | } 160 | } 161 | }, 162 | "ionic-cordova-serve": { 163 | "builder": "@ionic/angular-toolkit:cordova-serve", 164 | "options": { 165 | "cordovaBuildTarget": "app:ionic-cordova-build", 166 | "devServerTarget": "app:serve" 167 | }, 168 | "configurations": { 169 | "production": { 170 | "cordovaBuildTarget": "app:ionic-cordova-build:production", 171 | "devServerTarget": "app:serve:production" 172 | } 173 | } 174 | }, 175 | "deploy": { 176 | "builder": "@angular/fire:deploy", 177 | "options": {} 178 | } 179 | } 180 | } 181 | }, 182 | "cli": { 183 | "defaultCollection": "@ionic/angular-toolkit" 184 | }, 185 | "schematics": { 186 | "@ionic/angular-toolkit:component": { 187 | "styleext": "scss" 188 | }, 189 | "@ionic/angular-toolkit:page": { 190 | "styleext": "scss" 191 | } 192 | } 193 | } -------------------------------------------------------------------------------- /browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. 13 | -------------------------------------------------------------------------------- /capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "io.ionic.starter", 3 | "appName": "ionic5-firebase-authentication", 4 | "bundledWebRuntime": false, 5 | "npmClient": "npm", 6 | "webDir": "www", 7 | "cordova": {} 8 | } 9 | -------------------------------------------------------------------------------- /e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './src/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: require('path').join(__dirname, './tsconfig.json') 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('new App', () => { 4 | let page: AppPage; 5 | 6 | beforeEach(() => { 7 | page = new AppPage(); 8 | }); 9 | 10 | it('should be blank', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toContain('Start with Ionic UI Components'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.deepCss('app-root ion-content')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": [ 3 | { 4 | "target": "app", 5 | "public": "www", 6 | "ignore": [ 7 | "firebase.json", 8 | "**/.*", 9 | "**/node_modules/**" 10 | ], 11 | "rewrites": [ 12 | { 13 | "source": "**", 14 | "destination": "/index.html" 15 | } 16 | ] 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /ionic-v3/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | 10 | # We recommend you to keep these unchanged 11 | end_of_line = lf 12 | charset = utf-8 13 | trim_trailing_whitespace = true 14 | insert_final_newline = true 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /ionic-v3/.gitignore: -------------------------------------------------------------------------------- 1 | # Specifies intentionally untracked files to ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | *~ 5 | *.sw[mnpcod] 6 | *.log 7 | *.tmp 8 | *.tmp.* 9 | log.txt 10 | *.sublime-project 11 | *.sublime-workspace 12 | .vscode/ 13 | npm-debug.log* 14 | 15 | .idea/ 16 | .sourcemaps/ 17 | .sass-cache/ 18 | .tmp/ 19 | .versions/ 20 | coverage/ 21 | dist/ 22 | node_modules/ 23 | tmp/ 24 | temp/ 25 | hooks/ 26 | platforms/ 27 | plugins/ 28 | plugins/android.json 29 | plugins/ios.json 30 | www/ 31 | $RECYCLE.BIN/ 32 | 33 | .DS_Store 34 | Thumbs.db 35 | UserInterfaceState.xcuserstate 36 | -------------------------------------------------------------------------------- /ionic-v3/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 IonicThemes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ionic-v3/README.md: -------------------------------------------------------------------------------- 1 | ## Firebase Authentication in Ionic Framework Apps 2 | 3 | In this ionic tutorial we will learn how to configure a firebase application to enable an ionic 3 application to log in with both Email and Password and social providers such as Facebook, Twitter and Google. 4 | 5 | This repo is a simple ionic 3 app example with the goal of helping you integration Firebase Authentication to your Ionic app. 6 | 7 | ![demo](https://s3-us-west-2.amazonaws.com/ionicthemes/tutorials/screenshots/firebase-authentication-in-ionic-framework-apps/firebase-auth-login.png) 8 | ![demo](https://s3-us-west-2.amazonaws.com/ionicthemes/tutorials/screenshots/firebase-authentication-in-ionic-framework-apps/firebase-auth-register.png) 9 | 10 | **Note:** This code is for Ionic v3. 11 | - If you are working with Ionic v5 go to [ionic-v5 code](https://github.com/ionicthemes/ionic5-firebase-authentication) 12 | - If you are working with Ionic v1 go to [ionic-v1 code](https://github.com/ionicthemes/firebase-authentication-for-your-ionic-app). 13 | 14 | Read the complete Ionic Firebase Authentication Tutorial in https://ionicthemes.com/tutorials/about/firebase-authentication-in-ionic-framework-apps 15 | -------------------------------------------------------------------------------- /ionic-v3/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Firebase Authentication in Ionic Framework Apps 4 | Firebase Authentication example Ionic app 5 | IonicThemes Team 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ionic-v3/ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "app_id": "", 4 | "integrations": { 5 | "cordova": {} 6 | }, 7 | "type": "ionic-angular" 8 | } 9 | -------------------------------------------------------------------------------- /ionic-v3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ionic3FirebaseLogin", 3 | "version": "0.0.1", 4 | "author": "IonicThemes", 5 | "homepage": "https://ionicthemes.com/", 6 | "private": true, 7 | "scripts": { 8 | "clean": "ionic-app-scripts clean", 9 | "build": "ionic-app-scripts build", 10 | "lint": "ionic-app-scripts lint", 11 | "ionic:build": "ionic-app-scripts build", 12 | "ionic:serve": "ionic-app-scripts serve" 13 | }, 14 | "dependencies": { 15 | "@angular/animations": "5.2.10", 16 | "@angular/common": "5.2.10", 17 | "@angular/compiler": "5.2.10", 18 | "@angular/compiler-cli": "5.2.10", 19 | "@angular/core": "5.2.10", 20 | "@angular/forms": "5.2.10", 21 | "@angular/http": "5.2.10", 22 | "@angular/platform-browser": "5.2.10", 23 | "@angular/platform-browser-dynamic": "5.2.10", 24 | "@ionic-native/core": "4.4.0", 25 | "@ionic-native/facebook": "^4.5.3", 26 | "@ionic-native/google-plus": "^4.5.3", 27 | "@ionic-native/splash-screen": "4.4.0", 28 | "@ionic-native/status-bar": "4.4.0", 29 | "@ionic-native/twitter-connect": "^4.5.3", 30 | "@ionic/storage": "2.1.3", 31 | "angularfire2": "^5.0.0-rc.10", 32 | "cordova-android": "6.4.0", 33 | "cordova-ios": "~4.5.4", 34 | "cordova-plugin-device": "^2.0.2", 35 | "cordova-plugin-facebook4": "^1.10.1", 36 | "cordova-plugin-googleplus": "^5.3.0", 37 | "cordova-plugin-ionic-keyboard": "^2.1.2", 38 | "cordova-plugin-ionic-webview": "^1.2.1", 39 | "cordova-plugin-splashscreen": "^5.0.2", 40 | "cordova-plugin-whitelist": "^1.3.3", 41 | "firebase": "^5.0.4", 42 | "ionic-angular": "3.9.2", 43 | "ionicons": "3.0.0", 44 | "rxjs": "^5.5.6", 45 | "sw-toolbox": "3.6.0", 46 | "twitter-connect-plugin": "git+https://github.com/chroa/twitter-connect-plugin.git", 47 | "zone.js": "0.8.18" 48 | }, 49 | "devDependencies": { 50 | "@ionic/app-scripts": "3.1.8", 51 | "typescript": "2.4.2" 52 | }, 53 | "description": "An Ionic project", 54 | "cordova": { 55 | "platforms": [ 56 | "android", 57 | "ios" 58 | ], 59 | "plugins": { 60 | "cordova-plugin-device": {}, 61 | "cordova-plugin-facebook4": { 62 | "APP_ID": "186848361921511", 63 | "APP_NAME": "myApplication" 64 | }, 65 | "cordova-plugin-googleplus": { 66 | "REVERSED_CLIENT_ID": "com.googleusercontent.apps.401245627689-mcupb7o4sra8p6jqnlhe17d8b2rf4du6" 67 | }, 68 | "cordova-plugin-ionic-keyboard": {}, 69 | "cordova-plugin-ionic-webview": {}, 70 | "cordova-plugin-splashscreen": {}, 71 | "cordova-plugin-whitelist": {}, 72 | "twitter-connect-plugin": { 73 | "FABRIC_KEY": "dbf48d8f78bb16f9d9c54d737d7792891eb24607", 74 | "TWITTER_KEY": "kMV673U74jFqP3QZ81X4CduYL", 75 | "TWITTER_SECRET": "mb03DWehE5zRcb4g6Yl3PjJXlmCVEoDUxvCskotORCNy503rc4" 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /ionic-v3/resources/README.md: -------------------------------------------------------------------------------- 1 | These are Cordova resources. You can replace icon.png and splash.png and run 2 | `ionic cordova resources` to generate custom icons and splash screens for your 3 | app. See `ionic cordova resources --help` for details. 4 | 5 | Cordova reference documentation: 6 | 7 | - Icons: https://cordova.apache.org/docs/en/latest/config_ref/images.html 8 | - Splash Screens: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-splashscreen/ 9 | -------------------------------------------------------------------------------- /ionic-v3/resources/android/icon/drawable-hdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/icon/drawable-hdpi-icon.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/icon/drawable-ldpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/icon/drawable-ldpi-icon.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/icon/drawable-mdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/icon/drawable-mdpi-icon.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/icon/drawable-xhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/icon/drawable-xhdpi-icon.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/icon/drawable-xxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/icon/drawable-xxhdpi-icon.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/icon/drawable-xxxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/icon/drawable-xxxhdpi-icon.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-land-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-land-hdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-land-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-land-ldpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-land-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-land-mdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-land-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-land-xhdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-land-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-land-xxhdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-land-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-land-xxxhdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-port-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-port-hdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-port-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-port-ldpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-port-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-port-mdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-port-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-port-xhdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-port-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-port-xxhdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/android/splash/drawable-port-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/android/splash/drawable-port-xxxhdpi-screen.png -------------------------------------------------------------------------------- /ionic-v3/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/icon.png -------------------------------------------------------------------------------- /ionic-v3/resources/icon.png.md5: -------------------------------------------------------------------------------- 1 | 3f1bbdf1aefcb5ce7b60770ce907c68f -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-1024.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-40.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-40@2x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-40@3x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-50.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-50@2x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-60.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-60@2x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-60@3x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-72.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-72@2x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-76.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-76@2x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-83.5@2x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-small.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-small@2x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon-small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon-small@3x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/icon/icon@2x.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-568h@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-568h@2x~iphone.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-667h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-667h.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-736h.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-Landscape-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-Landscape-736h.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-Landscape@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-Landscape@2x~ipad.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-Landscape@~ipadpro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-Landscape@~ipadpro.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-Landscape~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-Landscape~ipad.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-Portrait@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-Portrait@2x~ipad.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-Portrait@~ipadpro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-Portrait@~ipadpro.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default-Portrait~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default-Portrait~ipad.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default@2x~iphone.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default@2x~universal~anyany.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default@2x~universal~anyany.png -------------------------------------------------------------------------------- /ionic-v3/resources/ios/splash/Default~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/ios/splash/Default~iphone.png -------------------------------------------------------------------------------- /ionic-v3/resources/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/resources/splash.png -------------------------------------------------------------------------------- /ionic-v3/resources/splash.png.md5: -------------------------------------------------------------------------------- 1 | 2412a8324a656ec5993eb50b3b293c69 -------------------------------------------------------------------------------- /ionic-v3/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Platform } from 'ionic-angular'; 3 | import { StatusBar } from '@ionic-native/status-bar'; 4 | import { SplashScreen } from '@ionic-native/splash-screen'; 5 | 6 | import { LoginPage } from '../pages/login/login'; 7 | @Component({ 8 | templateUrl: 'app.html' 9 | }) 10 | export class MyApp { 11 | rootPage:any = LoginPage; 12 | 13 | constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) { 14 | platform.ready().then(() => { 15 | // Okay, so the platform is ready and our plugins are available. 16 | // Here you can do any higher level native things you might need. 17 | statusBar.styleDefault(); 18 | splashScreen.hide(); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ionic-v3/src/app/app.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ionic-v3/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { ErrorHandler, NgModule } from '@angular/core'; 3 | import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; 4 | import { SplashScreen } from '@ionic-native/splash-screen'; 5 | import { StatusBar } from '@ionic-native/status-bar'; 6 | 7 | import { MyApp } from './app.component'; 8 | import { LoginPage } from '../pages/login/login'; 9 | import { RegisterPage } from '../pages/register/register'; 10 | import { UserPage} from '../pages/user/user'; 11 | 12 | 13 | import { AuthService } from '../pages/core/auth.service'; 14 | import { UserService } from '../pages/core/user.service'; 15 | 16 | import { AngularFireModule } from 'angularfire2'; 17 | import { AngularFireAuthModule } from 'angularfire2/auth'; 18 | import { environment } from '../environment/environment'; 19 | 20 | import { Facebook } from '@ionic-native/facebook'; 21 | import { GooglePlus } from '@ionic-native/google-plus'; 22 | import { TwitterConnect } from '@ionic-native/twitter-connect'; 23 | 24 | 25 | @NgModule({ 26 | declarations: [ 27 | MyApp, 28 | LoginPage, 29 | RegisterPage, 30 | UserPage 31 | ], 32 | imports: [ 33 | BrowserModule, 34 | IonicModule.forRoot(MyApp), 35 | AngularFireModule.initializeApp(environment.firebase), 36 | AngularFireAuthModule, 37 | ], 38 | bootstrap: [IonicApp], 39 | entryComponents: [ 40 | MyApp, 41 | LoginPage, 42 | RegisterPage, 43 | UserPage 44 | ], 45 | providers: [ 46 | StatusBar, 47 | SplashScreen, 48 | Facebook, 49 | GooglePlus, 50 | AuthService, 51 | TwitterConnect, 52 | UserService, 53 | {provide: ErrorHandler, useClass: IonicErrorHandler} 54 | ] 55 | }) 56 | export class AppModule {} 57 | -------------------------------------------------------------------------------- /ionic-v3/src/app/app.scss: -------------------------------------------------------------------------------- 1 | // http://ionicframework.com/docs/theming/ 2 | 3 | 4 | // App Global Sass 5 | // -------------------------------------------------- 6 | // Put style rules here that you want to apply globally. These 7 | // styles are for the entire app and not just one component. 8 | // Additionally, this file can be also used as an entry point 9 | // to import other Sass files to be included in the output CSS. 10 | // 11 | // Shared Sass variables, which can be used to adjust Ionic's 12 | // default Sass variables, belong in "theme/variables.scss". 13 | // 14 | // To declare rules for a specific mode, create a child rule 15 | // for the .md, .ios, or .wp mode classes. The mode class is 16 | // automatically applied to the element in the app. 17 | -------------------------------------------------------------------------------- /ionic-v3/src/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /ionic-v3/src/assets/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/src/assets/icon/favicon.ico -------------------------------------------------------------------------------- /ionic-v3/src/assets/imgs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/ionic-v3/src/assets/imgs/logo.png -------------------------------------------------------------------------------- /ionic-v3/src/environment/environment.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | // fbAppId: 186848361921511, 4 | googleWebClientId: '401245627689-ke4oci7bc8440anmpo4dms1od5keoome.apps.googleusercontent.com', 5 | firebase: { 6 | apiKey: "AIzaSyATBlD3709OkzGzNq5_a1Db2jk8-SBPDlg", 7 | authDomain: "thinking-return-94920.firebaseapp.com", 8 | databaseURL: "https://thinking-return-94920.firebaseio.com", 9 | projectId: "thinking-return-94920", 10 | storageBucket: "thinking-return-94920.appspot.com", 11 | messagingSenderId: "401245627689" 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /ionic-v3/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ionic App 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ionic-v3/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ionic", 3 | "short_name": "Ionic", 4 | "start_url": "index.html", 5 | "display": "standalone", 6 | "icons": [{ 7 | "src": "assets/imgs/logo.png", 8 | "sizes": "512x512", 9 | "type": "image/png" 10 | }], 11 | "background_color": "#4e8ef7", 12 | "theme_color": "#4e8ef7" 13 | } -------------------------------------------------------------------------------- /ionic-v3/src/pages/core/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { Platform } from 'ionic-angular'; 3 | import 'rxjs/add/operator/toPromise'; 4 | import { AngularFireAuth } from 'angularfire2/auth'; 5 | import * as firebase from 'firebase/app'; 6 | import { Facebook } from '@ionic-native/facebook'; 7 | import { GooglePlus } from '@ionic-native/google-plus'; 8 | import { TwitterConnect } from '@ionic-native/twitter-connect'; 9 | import { FirebaseUserModel } from './user.model'; 10 | import { environment } from '../../environment/environment'; 11 | 12 | 13 | @Injectable() 14 | export class AuthService { 15 | 16 | constructor( 17 | public afAuth: AngularFireAuth, 18 | public fb: Facebook, 19 | public googlePlus: GooglePlus, 20 | public tw : TwitterConnect, 21 | public platform: Platform 22 | ){} 23 | 24 | doRegister(value){ 25 | return new Promise((resolve, reject) => { 26 | firebase.auth().createUserWithEmailAndPassword(value.email, value.password) 27 | .then(res => { 28 | resolve(res); 29 | }, err => reject(err)) 30 | }) 31 | } 32 | 33 | doLogin(value){ 34 | return new Promise((resolve, reject) => { 35 | firebase.auth().signInWithEmailAndPassword(value.email, value.password) 36 | .then(res => { 37 | resolve(res); 38 | }, err => reject(err)) 39 | }) 40 | } 41 | 42 | doLogout(){ 43 | return new Promise((resolve, reject) => { 44 | if(firebase.auth().currentUser){ 45 | this.afAuth.auth.signOut() 46 | resolve(); 47 | } 48 | else { 49 | reject(); 50 | } 51 | }); 52 | } 53 | 54 | doGoogleLogin(){ 55 | return new Promise((resolve, reject) => { 56 | if (this.platform.is('cordova')) { 57 | this.googlePlus.login({ 58 | 'scopes': '', // optional, space-separated list of scopes, If not included or empty, defaults to `profile` and `email`. 59 | 'webClientId': environment.googleWebClientId, // optional clientId of your Web application from Credentials settings of your project - On Android, this MUST be included to get an idToken. On iOS, it is not required. 60 | 'offline': true 61 | }).then((response) => { 62 | const googleCredential = firebase.auth.GoogleAuthProvider.credential(response.idToken); 63 | firebase.auth().signInWithCredential(googleCredential) 64 | .then((user) => { 65 | resolve(); 66 | }); 67 | },(err) => { 68 | reject(err); 69 | }); 70 | } 71 | else{ 72 | this.afAuth.auth 73 | .signInWithPopup(new firebase.auth.GoogleAuthProvider()) 74 | .then((user) => { 75 | resolve() 76 | },(err) => { 77 | reject(err); 78 | }) 79 | } 80 | }) 81 | } 82 | 83 | doFacebookLogin(){ 84 | return new Promise((resolve, reject) => { 85 | if (this.platform.is('cordova')) { 86 | //["public_profile"] is the array of permissions, you can add more if you need 87 | this.fb.login(["public_profile"]) 88 | .then((response) => { 89 | const facebookCredential = firebase.auth.FacebookAuthProvider.credential(response.authResponse.accessToken); 90 | firebase.auth().signInWithCredential(facebookCredential) 91 | .then(user => resolve()); 92 | }, err => reject(err) 93 | ); 94 | } 95 | else { 96 | this.afAuth.auth 97 | .signInWithPopup(new firebase.auth.FacebookAuthProvider()) 98 | .then(result => { 99 | //Default facebook img is too small and we need a bigger image 100 | var bigImgUrl = "https://graph.facebook.com/" + result.additionalUserInfo.profile + "/picture?height=500"; 101 | // update profile to save the big fb profile img. 102 | firebase.auth().currentUser.updateProfile({ 103 | displayName: result.user.displayName, 104 | photoURL: bigImgUrl 105 | }).then(res => resolve() 106 | ,(err) => { 107 | reject(err); 108 | }); 109 | },(err) => { 110 | reject(err); 111 | }) 112 | } 113 | }) 114 | } 115 | 116 | doTwitterLogin(){ 117 | return new Promise((resolve, reject) => { 118 | // if we are in a mobile device we use the twitter native plugin 119 | 120 | if (this.platform.is('cordova')) { 121 | this.tw.login() 122 | .then((response) => { 123 | const twitterCredential = firebase.auth.TwitterAuthProvider.credential(response.token, response.secret); 124 | firebase.auth().signInWithCredential(twitterCredential) 125 | .then( 126 | user => resolve(), 127 | error => reject(error) 128 | ); 129 | }, 130 | err => { 131 | console.log(err); 132 | reject(err); 133 | } 134 | ); 135 | } 136 | else { 137 | this.afAuth.auth 138 | .signInWithPopup(new firebase.auth.TwitterAuthProvider()) 139 | .then(result => { 140 | //Default twitter img is just 48x48px and we need a bigger image https://developer.twitter.com/en/docs/accounts-and-users/user-profile-images-and-banners 141 | var bigImgUrl = (result.user.photoURL).replace('_normal', '_400x400'); 142 | 143 | // update profile to save the big tw profile img. 144 | firebase.auth().currentUser.updateProfile({ 145 | displayName: result.user.displayName, 146 | photoURL: bigImgUrl 147 | }).then(res => resolve(),(err) => { 148 | reject(err); 149 | }); 150 | },(err) => { 151 | reject(err); 152 | }) 153 | } 154 | }) 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/core/user.model.ts: -------------------------------------------------------------------------------- 1 | export class FirebaseUserModel { 2 | image: string; 3 | name: string; 4 | provider: string; 5 | 6 | constructor(){ 7 | this.image = ""; 8 | this.name = ""; 9 | this.provider = ""; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/core/user.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import 'rxjs/add/operator/toPromise'; 3 | import * as firebase from 'firebase/app'; 4 | import { FirebaseUserModel } from './user.model'; 5 | 6 | @Injectable() 7 | export class UserService { 8 | 9 | constructor(){} 10 | 11 | 12 | getCurrentUser(){ 13 | return new Promise((resolve, reject) => { 14 | firebase.auth().onAuthStateChanged(function(user){ 15 | let userModel = new FirebaseUserModel(); 16 | if (user) { 17 | if(user.providerData[0].providerId == 'password'){ 18 | //use a default image 19 | userModel.image = 'http://dsi-vd.github.io/patternlab-vd/images/fpo_avatar.png'; 20 | userModel.name = user.displayName; 21 | userModel.provider = user.providerData[0].providerId; 22 | return resolve(userModel); 23 | } 24 | else{ 25 | userModel.image = user.photoURL; 26 | userModel.name = user.displayName; 27 | userModel.provider = user.providerData[0].providerId; 28 | return resolve(userModel); 29 | } 30 | } else { 31 | reject('No user logged in'); 32 | } 33 | }) 34 | }) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/login/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Login 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | Email 12 | 13 | 14 | 15 | 16 | Password 17 | 18 | 19 | 20 | 23 | 24 | 25 |
26 |
27 |

No account yet? Create an account

28 |
29 |
30 | 31 |
32 | 33 | 34 | 35 |
36 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/login/login.scss: -------------------------------------------------------------------------------- 1 | page-login { 2 | ion-header { 3 | @include header-styles(color($colors, header, base), color($colors, header, contrast)); 4 | } 5 | 6 | .error-message{ 7 | color: red; 8 | } 9 | .submit-button 10 | { 11 | margin: 0px; 12 | margin-top: 20px; 13 | @include call-to-action-button-styles(color($colors, button, base), color($colors, button, contrast)); 14 | } 15 | 16 | .twitter-button{ 17 | margin: 0px; 18 | margin-top: 20px; 19 | @include call-to-action-button-styles(color($colors, twitter, base), color($colors, twitter, contrast)); 20 | } 21 | .facebook-button 22 | { 23 | margin: 0px; 24 | @include call-to-action-button-styles(color($colors, facebook, base), color($colors, facebook, contrast)); 25 | } 26 | 27 | .google-button 28 | { 29 | margin: 0px; 30 | margin-top: 20px; 31 | @include call-to-action-button-styles(color($colors, google, base), color($colors, google, contrast)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/login/login.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NavController } from 'ionic-angular'; 3 | 4 | import { FormBuilder, FormGroup, FormControl } from '@angular/forms'; 5 | 6 | import { RegisterPage } from '../register/register'; 7 | import { UserPage } from '../user/user'; 8 | import { AuthService } from '../core/auth.service'; 9 | 10 | 11 | @Component({ 12 | selector: 'page-login', 13 | templateUrl: 'login.html' 14 | }) 15 | export class LoginPage { 16 | 17 | loginForm: FormGroup; 18 | errorMessage: string = ''; 19 | 20 | constructor( 21 | public navCtrl: NavController, 22 | public authService: AuthService, 23 | public formBuilder: FormBuilder 24 | ) {} 25 | 26 | ionViewWillLoad(){ 27 | this.loginForm = this.formBuilder.group({ 28 | email: new FormControl(), 29 | password: new FormControl(), 30 | }); 31 | } 32 | 33 | tryLogin(value){ 34 | this.authService.doLogin(value) 35 | .then(res => { 36 | console.log(res); 37 | this.navCtrl.push(UserPage); 38 | }, err => { 39 | console.log(err); 40 | this.errorMessage = err.message; 41 | }) 42 | } 43 | 44 | tryFacebookLogin(){ 45 | this.authService.doFacebookLogin() 46 | .then((res) => { 47 | this.navCtrl.push(UserPage); 48 | }, (err) => { 49 | this.errorMessage = err.message; 50 | }); 51 | } 52 | 53 | tryGoogleLogin(){ 54 | this.authService.doGoogleLogin() 55 | .then((res) => { 56 | this.navCtrl.push(UserPage); 57 | }, (err) => { 58 | this.errorMessage = err.message; 59 | }); 60 | } 61 | 62 | tryTwitterLogin(){ 63 | this.authService.doTwitterLogin() 64 | .then((res) => { 65 | this.navCtrl.push(UserPage); 66 | }, (err) => { 67 | this.errorMessage = err.message; 68 | }); 69 | } 70 | 71 | goRegisterPage(){ 72 | this.navCtrl.push(RegisterPage); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/register/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Register 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | Email 12 | 13 | 14 | 15 | Password 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 |

Already have an account? Try to Log in

25 |
26 |
27 |
28 | 29 | 30 | 31 |
32 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/register/register.scss: -------------------------------------------------------------------------------- 1 | page-register { 2 | ion-header { 3 | @include header-styles(color($colors, header, base), color($colors, header, contrast)); 4 | } 5 | 6 | .error-message 7 | { 8 | color: red; 9 | } 10 | 11 | .success-message{ 12 | color: green; 13 | } 14 | 15 | .submit-button 16 | { 17 | margin: 0px; 18 | margin-top: 20px; 19 | @include call-to-action-button-styles(color($colors, button, base), color($colors, button, contrast)); 20 | } 21 | 22 | .twitter-button{ 23 | margin: 0px; 24 | margin-top: 20px; 25 | @include call-to-action-button-styles(color($colors, twitter, base), color($colors, twitter, contrast)); 26 | } 27 | .facebook-button 28 | { 29 | margin: 0px; 30 | @include call-to-action-button-styles(color($colors, facebook, base), color($colors, facebook, contrast)); 31 | } 32 | 33 | .google-button 34 | { 35 | margin: 0px; 36 | margin-top: 20px; 37 | @include call-to-action-button-styles(color($colors, google, base), color($colors, google, contrast)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/register/register.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NavController } from 'ionic-angular'; 3 | 4 | import { FormBuilder, FormGroup, FormControl } from '@angular/forms'; 5 | 6 | import { AuthService } from '../core/auth.service'; 7 | 8 | import { UserPage } from '../user/user'; 9 | 10 | 11 | 12 | @Component({ 13 | selector: 'page-register', 14 | templateUrl: 'register.html' 15 | }) 16 | export class RegisterPage { 17 | 18 | registerForm: FormGroup; 19 | errorMessage: string = ''; 20 | successMessage: string = ''; 21 | 22 | constructor( 23 | public navCtrl: NavController, 24 | public authService: AuthService, 25 | public formBuilder: FormBuilder 26 | ) {} 27 | 28 | ionViewWillLoad(){ 29 | this.registerForm = this.formBuilder.group({ 30 | email: new FormControl(), 31 | password: new FormControl() 32 | }); 33 | } 34 | 35 | tryRegister(value){ 36 | this.authService.doRegister(value) 37 | .then(res => { 38 | this.errorMessage = ""; 39 | this.successMessage = "Your account has been created. Please log in now."; 40 | }, err => { 41 | this.errorMessage = err.message; 42 | this.successMessage = ""; 43 | }) 44 | } 45 | 46 | tryFacebookLogin(){ 47 | this.authService.doFacebookLogin() 48 | .then((res) => { 49 | this.navCtrl.push(UserPage); 50 | }, (err) => { 51 | this.errorMessage = err.message; 52 | }); 53 | } 54 | 55 | tryGoogleLogin(){ 56 | this.authService.doGoogleLogin() 57 | .then((res) => { 58 | this.navCtrl.push(UserPage); 59 | }, (err) => { 60 | this.errorMessage = err.message; 61 | }); 62 | } 63 | 64 | tryTwitterLogin(){ 65 | this.authService.doTwitterLogin() 66 | .then((res) => { 67 | this.navCtrl.push(UserPage); 68 | }, (err) => { 69 | this.errorMessage = err.message; 70 | }); 71 | } 72 | 73 | goLoginPage(){ 74 | this.navCtrl.pop(); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/user/user.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | User 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {{user.name}} 12 | 13 |

14 | This is an example app of authentication using Firebase in an Ionic 3 app. 15 |

16 |
17 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/user/user.scss: -------------------------------------------------------------------------------- 1 | page-user { 2 | ion-header { 3 | @include header-styles(color($colors, header, base), color($colors, header, contrast)); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ionic-v3/src/pages/user/user.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NavController } from 'ionic-angular'; 3 | import { UserService } from '../core/user.service'; 4 | import { AuthService } from '../core/auth.service'; 5 | import { FirebaseUserModel } from '../core/user.model'; 6 | 7 | @Component({ 8 | selector: 'page-user', 9 | templateUrl: 'user.html' 10 | }) 11 | 12 | export class UserPage{ 13 | 14 | user: FirebaseUserModel = new FirebaseUserModel(); 15 | 16 | constructor( 17 | public navCtrl: NavController, 18 | public userService: UserService, 19 | public authService: AuthService 20 | ) {} 21 | 22 | ionViewWillLoad(){ 23 | this.userService.getCurrentUser() 24 | .then(user => { 25 | this.user = user; 26 | }, err => console.log(err)) 27 | } 28 | 29 | 30 | logout(){ 31 | this.authService.doLogout() 32 | .then((res) => { 33 | this.navCtrl.pop(); 34 | }, (error) => { 35 | console.log("Logout error", error); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ionic-v3/src/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check out https://googlechromelabs.github.io/sw-toolbox/ for 3 | * more info on how to use sw-toolbox to custom configure your service worker. 4 | */ 5 | 6 | 7 | 'use strict'; 8 | importScripts('./build/sw-toolbox.js'); 9 | 10 | self.toolbox.options.cache = { 11 | name: 'ionic-cache' 12 | }; 13 | 14 | // pre-cache our key assets 15 | self.toolbox.precache( 16 | [ 17 | './build/main.js', 18 | './build/vendor.js', 19 | './build/main.css', 20 | './build/polyfills.js', 21 | 'index.html', 22 | 'manifest.json' 23 | ] 24 | ); 25 | 26 | // dynamically cache any other local assets 27 | self.toolbox.router.any('/*', self.toolbox.fastest); 28 | 29 | // for any other requests go to the network, cache, 30 | // and then only use that cached resource if your user goes offline 31 | self.toolbox.router.default = self.toolbox.networkFirst; 32 | -------------------------------------------------------------------------------- /ionic-v3/src/theme/commons.scss: -------------------------------------------------------------------------------- 1 | @mixin call-to-action-button-styles($background, $color){ 2 | border-radius: 6px; 3 | color: $color; 4 | background-color: $background; 5 | font-size: 1.6rem; 6 | font-weight: 500; 7 | } 8 | 9 | @mixin header-styles($background, $color){ 10 | .toolbar-background 11 | { 12 | border: none !important; 13 | background-color: $background; 14 | } 15 | 16 | .toolbar-title, 17 | .back-button, 18 | .bar-button 19 | { 20 | color: $color; 21 | } 22 | } 23 | 24 | ion-header { 25 | @include header-styles(color($colors, header, base), color($colors, header, contrast)); 26 | } 27 | -------------------------------------------------------------------------------- /ionic-v3/src/theme/variables.scss: -------------------------------------------------------------------------------- 1 | // Ionic Variables and Theming. For more info, please see: 2 | // http://ionicframework.com/docs/theming/ 3 | 4 | // Font path is used to include ionicons, 5 | // roboto, and noto sans fonts 6 | $font-path: "../assets/fonts"; 7 | 8 | 9 | // The app direction is used to include 10 | // rtl styles in your app. For more info, please see: 11 | // http://ionicframework.com/docs/theming/rtl-support/ 12 | $app-direction: ltr; 13 | 14 | 15 | @import "ionic.globals"; 16 | 17 | 18 | // Shared Variables 19 | // -------------------------------------------------- 20 | // To customize the look and feel of this app, you can override 21 | // the Sass variables found in Ionic's source scss files. 22 | // To view all the possible Ionic variables, see: 23 | // http://ionicframework.com/docs/theming/overriding-ionic-variables/ 24 | $white: #FFFFFF; 25 | $theme-color-1: #00e9d5; 26 | $header-color: #488aff; 27 | 28 | 29 | // Named Color Variables 30 | // -------------------------------------------------- 31 | // Named colors makes it easy to reuse colors on various components. 32 | // It's highly recommended to change the default colors 33 | // to match your app's branding. Ionic uses a Sass map of 34 | // colors so you can add, rename and remove colors as needed. 35 | // The "primary" color is the only required color in the map. 36 | 37 | $colors: ( 38 | primary: #488aff, 39 | secondary: #32db64, 40 | danger: #f53d3d, 41 | light: #f4f4f4, 42 | dark: #222, 43 | twitter:( 44 | base: #00aced, 45 | contrast: $white 46 | ), 47 | facebook:( 48 | base: #3b5998, 49 | contrast: $white 50 | ), 51 | google:( 52 | base: #cc181e, 53 | contrast: $white 54 | ), 55 | button:( 56 | base: $theme-color-1, 57 | contrast: $white 58 | ), 59 | header:( 60 | base: $header-color, 61 | contrast: $white 62 | ) 63 | ); 64 | 65 | 66 | // App iOS Variables 67 | // -------------------------------------------------- 68 | // iOS only Sass variables can go here 69 | 70 | 71 | 72 | 73 | // App Material Design Variables 74 | // -------------------------------------------------- 75 | // Material Design only Sass variables can go here 76 | 77 | 78 | 79 | 80 | // App Windows Variables 81 | // -------------------------------------------------- 82 | // Windows only Sass variables can go here 83 | 84 | 85 | 86 | 87 | // App Theme 88 | // -------------------------------------------------- 89 | // Ionic apps can have different themes applied, which can 90 | // then be future customized. This import comes last 91 | // so that the above variables are used and Ionic's 92 | // default are overridden. 93 | 94 | @import "ionic.theme.default"; 95 | 96 | @import "./commons"; 97 | 98 | // Ionicons 99 | // -------------------------------------------------- 100 | // The premium icon font for Ionic. For more info, please see: 101 | // http://ionicframework.com/docs/ionicons/ 102 | 103 | @import "ionic.ionicons"; 104 | 105 | 106 | // Fonts 107 | // -------------------------------------------------- 108 | 109 | @import "roboto"; 110 | @import "noto-sans"; 111 | -------------------------------------------------------------------------------- /ionic-v3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "lib": [ 8 | "dom", 9 | "es2015" 10 | ], 11 | "module": "es2015", 12 | "moduleResolution": "node", 13 | "sourceMap": true, 14 | "target": "es5" 15 | }, 16 | "include": [ 17 | "src/**/*.ts" 18 | ], 19 | "exclude": [ 20 | "node_modules", 21 | "src/**/*.spec.ts", 22 | "src/**/__tests__/*.ts" 23 | ], 24 | "compileOnSave": false, 25 | "atom": { 26 | "rewriteTsconfig": false 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ionic-v3/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-duplicate-variable": true, 4 | "no-unused-variable": [ 5 | true 6 | ] 7 | }, 8 | "rulesDirectory": [ 9 | "node_modules/tslint-eslint-rules/dist/rules" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic5-firebase-authentication", 3 | "integrations": { 4 | "capacitor": {} 5 | }, 6 | "type": "angular" 7 | } 8 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../coverage'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic5-firebase-authentication", 3 | "version": "1.0.0", 4 | "author": "IonicThemes Team", 5 | "homepage": "https://ionicthemes.com/", 6 | "scripts": { 7 | "ng": "ng", 8 | "start": "ng serve", 9 | "build": "ng build", 10 | "test": "ng test", 11 | "lint": "ng lint", 12 | "e2e": "ng e2e" 13 | }, 14 | "private": true, 15 | "dependencies": { 16 | "@angular/common": "~10.2.0", 17 | "@angular/core": "~10.2.0", 18 | "@angular/fire": "^6.0.3", 19 | "@angular/forms": "~10.2.0", 20 | "@angular/platform-browser": "~10.2.0", 21 | "@angular/platform-browser-dynamic": "~10.2.0", 22 | "@angular/router": "~10.2.0", 23 | "@capacitor/core": "^2.4.2", 24 | "@ionic-native/core": "^5.0.7", 25 | "@ionic-native/splash-screen": "^5.0.0", 26 | "@ionic-native/status-bar": "^5.0.0", 27 | "@ionic/angular": "^5.4.1", 28 | "core-js": "^2.5.4", 29 | "firebase": "^7.24.0", 30 | "rxjs": "~6.6.3", 31 | "tslib": "^1.9.0", 32 | "zone.js": "~0.10.3" 33 | }, 34 | "devDependencies": { 35 | "@angular-devkit/architect": "^0.1002.0", 36 | "@angular-devkit/build-angular": "^0.1002.0", 37 | "@angular-devkit/core": "^10.2.0", 38 | "@angular-devkit/schematics": "^10.2.0", 39 | "@angular/cli": "~10.2.0", 40 | "@angular/compiler": "~10.2.0", 41 | "@angular/compiler-cli": "~10.2.0", 42 | "@angular/language-service": "~10.2.0", 43 | "@capacitor/cli": "^2.4.2", 44 | "@ionic/angular-toolkit": "^2.3.3", 45 | "@types/jasmine": "~3.5.0", 46 | "@types/jasminewd2": "~2.0.3", 47 | "@types/node": "^12.11.1", 48 | "codelyzer": "^5.1.2", 49 | "jasmine-core": "~3.5.0", 50 | "jasmine-spec-reporter": "~4.2.1", 51 | "karma": "~5.0.0", 52 | "karma-chrome-launcher": "~3.1.0", 53 | "karma-coverage-istanbul-reporter": "~2.1.0", 54 | "karma-jasmine": "~3.0.1", 55 | "karma-jasmine-html-reporter": "^1.4.2", 56 | "protractor": "~5.4.3", 57 | "ts-node": "~8.3.0", 58 | "tslint": "~6.1.0", 59 | "typescript": "~4.0.3" 60 | }, 61 | "description": "An Ionic project with Firebase Authentication" 62 | } 63 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; 3 | 4 | const routes: Routes = [ 5 | { 6 | path: 'sign-in', 7 | loadChildren: () => import('./sign-in/sign-in.module').then( m => m.SignInPageModule) 8 | }, 9 | { 10 | path: 'sign-up', 11 | loadChildren: () => import('./sign-up/sign-up.module').then( m => m.SignUpPageModule) 12 | }, 13 | { 14 | path: 'profile', 15 | loadChildren: () => import('./profile/profile.module').then( m => m.ProfilePageModule) 16 | }, 17 | { 18 | path: '', 19 | redirectTo: 'sign-in', 20 | pathMatch: 'full' 21 | }, 22 | ]; 23 | 24 | @NgModule({ 25 | imports: [ 26 | RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }) 27 | ], 28 | exports: [RouterModule] 29 | }) 30 | export class AppRoutingModule { } 31 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { TestBed, async } from '@angular/core/testing'; 3 | 4 | import { Platform } from '@ionic/angular'; 5 | import { SplashScreen } from '@ionic-native/splash-screen/ngx'; 6 | import { StatusBar } from '@ionic-native/status-bar/ngx'; 7 | 8 | import { AppComponent } from './app.component'; 9 | 10 | describe('AppComponent', () => { 11 | 12 | let statusBarSpy, splashScreenSpy, platformReadySpy, platformSpy; 13 | 14 | beforeEach(async(() => { 15 | statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']); 16 | splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']); 17 | platformReadySpy = Promise.resolve(); 18 | platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy }); 19 | 20 | TestBed.configureTestingModule({ 21 | declarations: [AppComponent], 22 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 23 | providers: [ 24 | { provide: StatusBar, useValue: statusBarSpy }, 25 | { provide: SplashScreen, useValue: splashScreenSpy }, 26 | { provide: Platform, useValue: platformSpy }, 27 | ], 28 | }).compileComponents(); 29 | })); 30 | 31 | it('should create the app', () => { 32 | const fixture = TestBed.createComponent(AppComponent); 33 | const app = fixture.debugElement.componentInstance; 34 | expect(app).toBeTruthy(); 35 | }); 36 | 37 | it('should initialize the app', async () => { 38 | TestBed.createComponent(AppComponent); 39 | expect(platformSpy.ready).toHaveBeenCalled(); 40 | await platformReadySpy; 41 | expect(statusBarSpy.styleDefault).toHaveBeenCalled(); 42 | expect(splashScreenSpy.hide).toHaveBeenCalled(); 43 | }); 44 | 45 | // TODO: add more tests! 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | import { Platform } from '@ionic/angular'; 4 | import { SplashScreen } from '@ionic-native/splash-screen/ngx'; 5 | import { StatusBar } from '@ionic-native/status-bar/ngx'; 6 | 7 | @Component({ 8 | selector: 'app-root', 9 | templateUrl: 'app.component.html' 10 | }) 11 | export class AppComponent { 12 | constructor( 13 | private platform: Platform, 14 | private splashScreen: SplashScreen, 15 | private statusBar: StatusBar 16 | ) { 17 | this.initializeApp(); 18 | } 19 | 20 | initializeApp() { 21 | this.platform.ready().then(() => { 22 | this.statusBar.styleDefault(); 23 | this.splashScreen.hide(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { RouteReuseStrategy } from '@angular/router'; 4 | 5 | import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; 6 | import { SplashScreen } from '@ionic-native/splash-screen/ngx'; 7 | import { StatusBar } from '@ionic-native/status-bar/ngx'; 8 | 9 | import { AppComponent } from './app.component'; 10 | import { AppRoutingModule } from './app-routing.module'; 11 | 12 | import { AngularFireModule } from '@angular/fire'; 13 | import { AngularFireAuthModule } from '@angular/fire/auth'; 14 | import { environment } from '../environments/environment'; 15 | import { FirebaseAuthService } from './firebase-auth.service'; 16 | 17 | @NgModule({ 18 | declarations: [AppComponent], 19 | imports: [ 20 | BrowserModule, 21 | IonicModule.forRoot(), 22 | AppRoutingModule, 23 | AngularFireModule.initializeApp(environment.firebase), 24 | AngularFireAuthModule 25 | ], 26 | providers: [ 27 | StatusBar, 28 | SplashScreen, 29 | FirebaseAuthService, 30 | { provide: RouteReuseStrategy, useClass: IonicRouteStrategy } 31 | ], 32 | bootstrap: [AppComponent] 33 | }) 34 | export class AppModule {} 35 | -------------------------------------------------------------------------------- /src/app/firebase-auth.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { AngularFireAuth } from '@angular/fire/auth'; 3 | import { Observable, Subject, from } from 'rxjs'; 4 | import { Platform } from '@ionic/angular'; 5 | import { User, auth } from 'firebase/app'; 6 | import { ProfileModel } from './profile/profile.model'; 7 | import { filter, map, take } from 'rxjs/operators'; 8 | 9 | @Injectable() 10 | export class FirebaseAuthService { 11 | 12 | currentUser: User; 13 | userProviderAdditionalInfo: any; 14 | redirectResult: Subject = new Subject(); 15 | 16 | constructor( 17 | public angularFireAuth: AngularFireAuth, 18 | public platform: Platform 19 | ) { 20 | this.angularFireAuth.onAuthStateChanged((user) => { 21 | if (user) { 22 | // User is signed in. 23 | this.currentUser = user; 24 | } else { 25 | // No user is signed in. 26 | this.currentUser = null; 27 | } 28 | }); 29 | 30 | // when using signInWithRedirect, this listens for the redirect results 31 | this.angularFireAuth.getRedirectResult() 32 | .then((result) => { 33 | // result.credential.accessToken gives you the Provider Access Token. You can use it to access the Provider API. 34 | if (result.user) { 35 | this.setProviderAdditionalInfo(result.additionalUserInfo.profile); 36 | this.currentUser = result.user; 37 | this.redirectResult.next(result); 38 | } 39 | }, (error) => { 40 | this.redirectResult.next({error: error.code}); 41 | }); 42 | } 43 | 44 | getRedirectResult(): Observable { 45 | return this.redirectResult.asObservable(); 46 | } 47 | 48 | setProviderAdditionalInfo(additionalInfo: any) { 49 | this.userProviderAdditionalInfo = {...additionalInfo}; 50 | } 51 | 52 | public getProfileDataSource() { 53 | return this.angularFireAuth.user 54 | .pipe( 55 | filter((user: User) => user != null), 56 | map((user: User) => { 57 | return this.getProfileData(); 58 | }), 59 | take(1) // this.angularFireAuth.user never completes so we use take(1) in order to complete after the first value is emitted 60 | ); 61 | } 62 | 63 | public getProfileData() { 64 | const userModel = new ProfileModel(); 65 | let providerData : any = this.currentUser.providerData[0]; 66 | 67 | if (this.userProviderAdditionalInfo) { 68 | providerData = {...providerData, ...this.userProviderAdditionalInfo}; 69 | } 70 | 71 | // Default imgs are too small and our app needs a bigger image 72 | switch (providerData.providerId) { 73 | case 'facebook.com': 74 | userModel.image = providerData.photoURL + '?height=400'; 75 | break; 76 | case 'password': 77 | userModel.image = 'https://s3-us-west-2.amazonaws.com/ionicthemes/otros/avatar-placeholder.png'; 78 | break; 79 | case 'twitter.com': 80 | userModel.image = providerData.photoURL.replace('_normal', '_400x400'); 81 | break; 82 | case 'google.com': 83 | userModel.image = providerData.photoURL.split('=')[0]; 84 | break; 85 | default: 86 | userModel.image = providerData.photoURL; 87 | } 88 | userModel.name = providerData.name || providerData.displayName || 'What\'s your name?'; 89 | userModel.role = 'How would you describe yourself?'; 90 | userModel.description = providerData.description || 'Anything else you would like to share with the world?'; 91 | userModel.phoneNumber = providerData.phoneNumber || 'Is there a number where I can reach you?'; 92 | userModel.email = providerData.email || 'Where can I send you emails?'; 93 | userModel.provider = (providerData.providerId !== 'password') ? providerData.providerId : 'Credentials'; 94 | 95 | return userModel; 96 | } 97 | 98 | signOut(): Observable { 99 | return from(this.angularFireAuth.signOut()); 100 | } 101 | 102 | signInWithEmail(email: string, password: string): Promise { 103 | return this.angularFireAuth.signInWithEmailAndPassword(email, password); 104 | } 105 | 106 | signUpWithEmail(email: string, password: string): Promise { 107 | return this.angularFireAuth.createUserWithEmailAndPassword(email, password); 108 | } 109 | 110 | socialSignIn(providerName: string, scopes?: Array): Promise { 111 | const provider = new auth.OAuthProvider(providerName); 112 | 113 | // add any permission scope you need 114 | if (scopes) { 115 | scopes.forEach(scope => { 116 | provider.addScope(scope); 117 | }); 118 | } 119 | 120 | if (this.platform.is('desktop')) { 121 | return this.angularFireAuth.signInWithPopup(provider); 122 | } else { 123 | // web but not desktop, for example mobile PWA 124 | return this.angularFireAuth.signInWithRedirect(provider); 125 | } 126 | } 127 | 128 | signInWithFacebook() { 129 | const provider = new auth.FacebookAuthProvider(); 130 | // const scopes = ['user_birthday']; 131 | return this.socialSignIn(provider.providerId); 132 | } 133 | 134 | signInWithGoogle() { 135 | const provider = new auth.GoogleAuthProvider(); 136 | const scopes = ['profile', 'email']; 137 | return this.socialSignIn(provider.providerId, scopes); 138 | } 139 | 140 | signInWithTwitter() { 141 | const provider = new auth.TwitterAuthProvider(); 142 | return this.socialSignIn(provider.providerId); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/app/profile/profile.model.ts: -------------------------------------------------------------------------------- 1 | export class ProfileModel { 2 | image: string; 3 | name: string; 4 | role: string; 5 | description: string; 6 | email: string; 7 | provider: string; 8 | phoneNumber: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/profile/profile.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { IonicModule } from '@ionic/angular'; 6 | 7 | import { ProfilePage } from './profile.page'; 8 | import { RouterModule, Routes } from '@angular/router'; 9 | import { ProfilePageResolver } from './profile.resolver'; 10 | 11 | import { AngularFireAuthGuard, redirectUnauthorizedTo } from '@angular/fire/auth-guard'; 12 | 13 | const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['sign-in']); 14 | 15 | const routes: Routes = [ 16 | { 17 | path: '', 18 | component: ProfilePage, 19 | canActivate: [AngularFireAuthGuard], 20 | data: { authGuardPipe: redirectUnauthorizedToLogin }, 21 | resolve: { 22 | data: ProfilePageResolver 23 | } 24 | } 25 | ]; 26 | 27 | @NgModule({ 28 | imports: [ 29 | CommonModule, 30 | FormsModule, 31 | IonicModule, 32 | RouterModule.forChild(routes), 33 | ], 34 | declarations: [ProfilePage], 35 | providers: [ProfilePageResolver] 36 | }) 37 | export class ProfilePageModule {} 38 | -------------------------------------------------------------------------------- /src/app/profile/profile.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 |

Mobile

22 |

23 | {{user.phoneNumber}} 24 |

25 |
26 | 27 |

Email

28 |

29 | {{user.email}} 30 |

31 |
32 | 33 |

Auth Provider

34 |

35 | {{user.provider}} 36 |

37 |
38 | 39 | Sign out 40 | 41 |
42 |
43 | -------------------------------------------------------------------------------- /src/app/profile/profile.page.scss: -------------------------------------------------------------------------------- 1 | .profile-content { 2 | --padding-bottom: 16px; 3 | --padding-end: 16px; 4 | --padding-start: 16px; 5 | --padding-top: 16px; 6 | 7 | .user-image { 8 | border-radius: 4%; 9 | } 10 | 11 | .user-details-wrapper { 12 | justify-content: center; 13 | 14 | .user-image-wrapper { 15 | text-align: center; 16 | } 17 | 18 | .user-info-wrapper { 19 | text-align: center; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/profile/profile.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { ProfilePage } from './profile.page'; 5 | 6 | describe('ProfilePage', () => { 7 | let component: ProfilePage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ ProfilePage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(ProfilePage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/app/profile/profile.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { ProfileModel } from './profile.model'; 4 | import { FirebaseAuthService } from '../firebase-auth.service'; 5 | 6 | @Component({ 7 | selector: 'app-profile', 8 | templateUrl: './profile.page.html', 9 | styleUrls: ['./profile.page.scss'], 10 | }) 11 | export class ProfilePage implements OnInit { 12 | user: ProfileModel; 13 | 14 | constructor( 15 | private router: Router, 16 | private route: ActivatedRoute, 17 | private authService: FirebaseAuthService 18 | ) { } 19 | 20 | ngOnInit() { 21 | this.route.data 22 | .subscribe((result) => { 23 | this.user = result['data']; 24 | }, (err) => {}) 25 | } 26 | 27 | signOut() { 28 | this.authService.signOut().subscribe(() => { 29 | // Sign-out successful. 30 | this.router.navigate(['sign-in']); 31 | }, (error) => { 32 | console.log('signout error', error); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/profile/profile.resolver.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Resolve } from '@angular/router'; 3 | import { FirebaseAuthService } from '../firebase-auth.service'; 4 | 5 | @Injectable() 6 | export class ProfilePageResolver implements Resolve { 7 | 8 | constructor(private firebaseAuthService: FirebaseAuthService) {} 9 | 10 | resolve() { 11 | return this.firebaseAuthService.getProfileDataSource(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/app/sign-in/sign-in.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { IonicModule } from '@ionic/angular'; 4 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 5 | import { SignInPage } from './sign-in.page'; 6 | import { Routes, RouterModule } from '@angular/router'; 7 | 8 | const routes: Routes = [ 9 | { 10 | path: '', 11 | component: SignInPage, 12 | } 13 | ]; 14 | 15 | @NgModule({ 16 | imports: [ 17 | CommonModule, 18 | FormsModule, 19 | ReactiveFormsModule, 20 | IonicModule, 21 | RouterModule.forChild(routes), 22 | ], 23 | declarations: [SignInPage] 24 | }) 25 | export class SignInPageModule {} 26 | -------------------------------------------------------------------------------- /src/app/sign-in/sign-in.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 57 | -------------------------------------------------------------------------------- /src/app/sign-in/sign-in.page.scss: -------------------------------------------------------------------------------- 1 | .sign-in-content { 2 | text-align: center; 3 | --padding-bottom: 16px; 4 | --padding-end: 16px; 5 | --padding-start: 16px; 6 | --padding-top: 16px; 7 | 8 | .auth-title { 9 | font-weight: bold; 10 | margin-bottom: 64px; 11 | letter-spacing: 0.6px; 12 | } 13 | 14 | .social-auth-options { 15 | .options-divider { 16 | text-align: center; 17 | } 18 | } 19 | 20 | .inputs-list { 21 | .input-item { 22 | --padding-start: 0px; 23 | --padding-end: 0px; 24 | --inner-padding-end: 0px; 25 | } 26 | } 27 | 28 | .error-container { 29 | .error-message { 30 | margin: 16px 0px; 31 | display: flex; 32 | align-items: center; 33 | color: var(--ion-color-danger); 34 | font-size: 14px; 35 | 36 | ion-icon { 37 | font-size: 16px; 38 | padding-inline-end: 8px; 39 | } 40 | } 41 | } 42 | 43 | .sign-in-btn { 44 | margin: 16px 0px; 45 | } 46 | 47 | .sign-up-btn-wrapper { 48 | justify-content: flex-end; 49 | align-items: center; 50 | 51 | .sign-up-btn { 52 | --padding-end: 0px; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/app/sign-in/sign-in.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { SignInPage } from './sign-in.page'; 5 | 6 | describe('SignInPage', () => { 7 | let component: SignInPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ SignInPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(SignInPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/app/sign-in/sign-in.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, NgZone } from '@angular/core'; 2 | import { AngularFireAuth } from '@angular/fire/auth'; 3 | import { FormGroup, FormControl, Validators } from '@angular/forms'; 4 | import { Router } from '@angular/router'; 5 | import { FirebaseAuthService } from '../firebase-auth.service'; 6 | import { Subscription } from 'rxjs'; 7 | 8 | @Component({ 9 | selector: 'app-sign-in', 10 | templateUrl: 'sign-in.page.html', 11 | styleUrls: ['sign-in.page.scss'], 12 | }) 13 | export class SignInPage { 14 | signInForm: FormGroup; 15 | submitError: string; 16 | authRedirectResult: Subscription; 17 | 18 | validation_messages = { 19 | 'email': [ 20 | { type: 'required', message: 'Email is required.' }, 21 | { type: 'pattern', message: 'Enter a valid email.' } 22 | ], 23 | 'password': [ 24 | { type: 'required', message: 'Password is required.' }, 25 | { type: 'minlength', message: 'Password must be at least 6 characters long.' } 26 | ] 27 | }; 28 | 29 | constructor( 30 | public angularFire: AngularFireAuth, 31 | public router: Router, 32 | private ngZone: NgZone, 33 | private authService: FirebaseAuthService 34 | ) { 35 | this.signInForm = new FormGroup({ 36 | 'email': new FormControl('', Validators.compose([ 37 | Validators.required, 38 | Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$') 39 | ])), 40 | 'password': new FormControl('', Validators.compose([ 41 | Validators.minLength(6), 42 | Validators.required 43 | ])) 44 | }); 45 | 46 | // Get firebase authentication redirect result invoken when using signInWithRedirect() 47 | // signInWithRedirect() is only used when client is in web but not desktop 48 | this.authRedirectResult = this.authService.getRedirectResult() 49 | .subscribe(result => { 50 | if (result.user) { 51 | this.redirectLoggedUserToProfilePage(); 52 | } else if (result.error) { 53 | this.submitError = result.error; 54 | } 55 | }); 56 | } 57 | 58 | // Once the auth provider finished the authentication flow, and the auth redirect completes, 59 | // redirect the user to the profile page 60 | redirectLoggedUserToProfilePage() { 61 | // As we are calling the Angular router navigation inside a subscribe method, the navigation will be triggered outside Angular zone. 62 | // That's why we need to wrap the router navigation call inside an ngZone wrapper 63 | this.ngZone.run(() => { 64 | this.router.navigate(['profile']); 65 | }); 66 | } 67 | 68 | signInWithEmail() { 69 | this.authService.signInWithEmail(this.signInForm.value['email'], this.signInForm.value['password']) 70 | .then(user => { 71 | // navigate to user profile 72 | this.redirectLoggedUserToProfilePage(); 73 | }) 74 | .catch(error => { 75 | this.submitError = error.message; 76 | }); 77 | } 78 | 79 | facebookSignIn() { 80 | this.authService.signInWithFacebook() 81 | .then((result: any) => { 82 | if (result.additionalUserInfo) { 83 | this.authService.setProviderAdditionalInfo(result.additionalUserInfo.profile); 84 | } 85 | // This gives you a Facebook Access Token. You can use it to access the Facebook API. 86 | // const token = result.credential.accessToken; 87 | // The signed-in user info is in result.user; 88 | this.redirectLoggedUserToProfilePage(); 89 | }).catch((error) => { 90 | // Handle Errors here. 91 | console.log(error); 92 | }); 93 | } 94 | 95 | googleSignIn() { 96 | this.authService.signInWithGoogle() 97 | .then((result: any) => { 98 | if (result.additionalUserInfo) { 99 | this.authService.setProviderAdditionalInfo(result.additionalUserInfo.profile); 100 | } 101 | // This gives you a Google Access Token. You can use it to access the Google API. 102 | // const token = result.credential.accessToken; 103 | // The signed-in user info is in result.user; 104 | this.redirectLoggedUserToProfilePage(); 105 | }).catch((error) => { 106 | // Handle Errors here. 107 | console.log(error); 108 | }); 109 | } 110 | 111 | twitterSignIn() { 112 | this.authService.signInWithTwitter() 113 | .then((result: any) => { 114 | if (result.additionalUserInfo) { 115 | this.authService.setProviderAdditionalInfo(result.additionalUserInfo.profile); 116 | } 117 | // This gives you a Twitter Access Token. You can use it to access the Twitter API. 118 | // const token = result.credential.accessToken; 119 | // The signed-in user info is in result.user; 120 | this.redirectLoggedUserToProfilePage(); 121 | }).catch((error) => { 122 | // Handle Errors here. 123 | console.log(error); 124 | }); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/app/sign-up/sign-up.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 4 | 5 | import { IonicModule } from '@ionic/angular'; 6 | 7 | import { SignUpPage } from './sign-up.page'; 8 | import { Routes, RouterModule } from '@angular/router'; 9 | 10 | const routes: Routes = [ 11 | { 12 | path: '', 13 | component: SignUpPage, 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [ 19 | CommonModule, 20 | FormsModule, 21 | ReactiveFormsModule, 22 | IonicModule, 23 | RouterModule.forChild(routes), 24 | ], 25 | declarations: [SignUpPage] 26 | }) 27 | export class SignUpPageModule {} 28 | -------------------------------------------------------------------------------- /src/app/sign-up/sign-up.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 61 | -------------------------------------------------------------------------------- /src/app/sign-up/sign-up.page.scss: -------------------------------------------------------------------------------- 1 | .sign-up-content { 2 | text-align: center; 3 | --padding-bottom: 16px; 4 | --padding-end: 16px; 5 | --padding-start: 16px; 6 | --padding-top: 16px; 7 | 8 | .auth-title { 9 | font-weight: bold; 10 | margin-bottom: 64px; 11 | letter-spacing: 0.6px; 12 | } 13 | 14 | .social-auth-options { 15 | .options-divider { 16 | text-align: center; 17 | } 18 | } 19 | 20 | .inputs-list { 21 | .input-item { 22 | --padding-start: 0px; 23 | --padding-end: 0px; 24 | --inner-padding-end: 0px; 25 | } 26 | } 27 | 28 | .error-container { 29 | .error-message { 30 | margin: 16px 0px; 31 | display: flex; 32 | align-items: center; 33 | color: var(--ion-color-danger); 34 | font-size: 14px; 35 | 36 | ion-icon { 37 | font-size: 16px; 38 | padding-inline-end: 8px; 39 | } 40 | } 41 | } 42 | 43 | .sign-up-btn { 44 | margin: 16px 0px; 45 | } 46 | 47 | .sign-in-btn-wrapper { 48 | justify-content: flex-end; 49 | align-items: center; 50 | 51 | .sign-in-btn { 52 | --padding-end: 0px; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/app/sign-up/sign-up.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | 4 | import { SignUpPage } from './sign-up.page'; 5 | 6 | describe('SignUpPage', () => { 7 | let component: SignUpPage; 8 | let fixture: ComponentFixture; 9 | 10 | beforeEach(async(() => { 11 | TestBed.configureTestingModule({ 12 | declarations: [ SignUpPage ], 13 | imports: [IonicModule.forRoot()] 14 | }).compileComponents(); 15 | 16 | fixture = TestBed.createComponent(SignUpPage); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | })); 20 | 21 | it('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/app/sign-up/sign-up.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, NgZone } from '@angular/core'; 2 | import { AngularFireAuth } from '@angular/fire/auth'; 3 | import { Router } from '@angular/router'; 4 | import { FormGroup, FormControl, Validators } from '@angular/forms'; 5 | import { FirebaseAuthService } from '../firebase-auth.service'; 6 | import { Subscription } from 'rxjs'; 7 | 8 | @Component({ 9 | selector: 'app-sign-up', 10 | templateUrl: './sign-up.page.html', 11 | styleUrls: ['./sign-up.page.scss'], 12 | }) 13 | export class SignUpPage { 14 | signUpForm: FormGroup; 15 | submitError: string; 16 | authRedirectResult: Subscription; 17 | 18 | validation_messages = { 19 | 'email': [ 20 | { type: 'required', message: 'Email is required.' }, 21 | { type: 'pattern', message: 'Enter a valid email.' } 22 | ], 23 | 'password': [ 24 | { type: 'required', message: 'Password is required.' }, 25 | { type: 'minlength', message: 'Password must be at least 6 characters long.' } 26 | ] 27 | }; 28 | 29 | constructor( 30 | public angularFire: AngularFireAuth, 31 | public router: Router, 32 | private ngZone: NgZone, 33 | private authService: FirebaseAuthService 34 | ) { 35 | this.signUpForm = new FormGroup({ 36 | 'email': new FormControl('', Validators.compose([ 37 | Validators.required, 38 | Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$') 39 | ])), 40 | 'password': new FormControl('', Validators.compose([ 41 | Validators.minLength(6), 42 | Validators.required 43 | ])) 44 | }); 45 | // Get firebase authentication redirect result invoken when using signInWithRedirect() 46 | // signInWithRedirect() is only used when client is in web but not desktop 47 | this.authRedirectResult = this.authService.getRedirectResult() 48 | .subscribe(result => { 49 | if (result.user) { 50 | this.redirectLoggedUserToProfilePage(); 51 | } else if (result.error) { 52 | this.submitError = result.error; 53 | } 54 | }); 55 | } 56 | 57 | // Once the auth provider finished the authentication flow, and the auth redirect completes, 58 | // redirect the user to the profile page 59 | redirectLoggedUserToProfilePage() { 60 | // As we are calling the Angular router navigation inside a subscribe method, the navigation will be triggered outside Angular zone. 61 | // That's why we need to wrap the router navigation call inside an ngZone wrapper 62 | this.ngZone.run(() => { 63 | this.router.navigate(['profile']); 64 | }); 65 | } 66 | 67 | signUpWithEmail() { 68 | this.authService.signUpWithEmail(this.signUpForm.value['email'], this.signUpForm.value['password']) 69 | .then(user => { 70 | // navigate to user profile 71 | this.redirectLoggedUserToProfilePage(); 72 | }) 73 | .catch(error => { 74 | this.submitError = error.message; 75 | }); 76 | } 77 | 78 | facebookSignUp() { 79 | this.authService.signInWithFacebook() 80 | .then((result: any) => { 81 | if (result.additionalUserInfo) { 82 | this.authService.setProviderAdditionalInfo(result.additionalUserInfo.profile); 83 | } 84 | // This gives you a Facebook Access Token. You can use it to access the Facebook API. 85 | // const token = result.credential.accessToken; 86 | // The signed-in user info is in result.user; 87 | this.redirectLoggedUserToProfilePage(); 88 | }).catch((error) => { 89 | // Handle Errors here. 90 | console.log(error); 91 | }); 92 | } 93 | 94 | googleSignUp() { 95 | this.authService.signInWithGoogle() 96 | .then((result: any) => { 97 | if (result.additionalUserInfo) { 98 | this.authService.setProviderAdditionalInfo(result.additionalUserInfo.profile); 99 | } 100 | // This gives you a Google Access Token. You can use it to access the Google API. 101 | // const token = result.credential.accessToken; 102 | // The signed-in user info is in result.user; 103 | this.redirectLoggedUserToProfilePage(); 104 | }).catch((error) => { 105 | // Handle Errors here. 106 | console.log(error); 107 | }); 108 | } 109 | 110 | twitterSignUp() { 111 | this.authService.signInWithTwitter() 112 | .then((result: any) => { 113 | if (result.additionalUserInfo) { 114 | this.authService.setProviderAdditionalInfo(result.additionalUserInfo.profile); 115 | } 116 | // This gives you a Twitter Access Token. You can use it to access the Twitter API. 117 | // const token = result.credential.accessToken; 118 | // The signed-in user info is in result.user; 119 | this.redirectLoggedUserToProfilePage(); 120 | }).catch((error) => { 121 | // Handle Errors here. 122 | console.log(error); 123 | }); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/assets/icon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ionicthemes/ionic5-firebase-authentication/c599afaddf333e94b7c7bfc4c906b216c47bb252/src/assets/icon/favicon.png -------------------------------------------------------------------------------- /src/assets/shapes.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | firebase: { 4 | apiKey: "AIzaSyB_hifCjvJb7jf3hnZozfzlnJQ6N0iYuXI", 5 | authDomain: "ionic5-firebase-authentication.firebaseapp.com", 6 | databaseURL: "https://ionic5-firebase-authentication.firebaseio.com", 7 | projectId: "ionic5-firebase-authentication", 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | firebase: { 8 | apiKey: "AIzaSyB_hifCjvJb7jf3hnZozfzlnJQ6N0iYuXI", 9 | authDomain: "ionic5-firebase-authentication.firebaseapp.com", 10 | databaseURL: "https://ionic5-firebase-authentication.firebaseio.com", 11 | projectId: "ionic5-firebase-authentication", 12 | } 13 | }; 14 | 15 | /* 16 | * For easier debugging in development mode, you can import the following file 17 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 18 | * 19 | * This import should be commented out in production mode because it will have a negative impact 20 | * on performance if an error is thrown. 21 | */ 22 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 23 | -------------------------------------------------------------------------------- /src/global.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * App Global CSS 3 | * ---------------------------------------------------------------------------- 4 | * Put style rules here that you want to apply globally. These styles are for 5 | * the entire app and not just one component. Additionally, this file can be 6 | * used as an entry point to import other CSS/Sass files to be included in the 7 | * output CSS. 8 | * For more information on global stylesheets, visit the documentation: 9 | * https://ionicframework.com/docs/layout/global-stylesheets 10 | */ 11 | 12 | /* Core CSS required for Ionic components to work properly */ 13 | @import "~@ionic/angular/css/core.css"; 14 | 15 | /* Basic CSS for apps built with Ionic */ 16 | @import "~@ionic/angular/css/normalize.css"; 17 | @import "~@ionic/angular/css/structure.css"; 18 | @import "~@ionic/angular/css/typography.css"; 19 | @import '~@ionic/angular/css/display.css'; 20 | 21 | /* Optional CSS utils that can be commented out */ 22 | @import "~@ionic/angular/css/padding.css"; 23 | @import "~@ionic/angular/css/float-elements.css"; 24 | @import "~@ionic/angular/css/text-alignment.css"; 25 | @import "~@ionic/angular/css/text-transformation.css"; 26 | @import "~@ionic/angular/css/flex-utils.css"; 27 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Ionic App 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.log(err)); 13 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | import './zone-flags'; 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | 61 | import 'zone.js/dist/zone'; // Included with Angular CLI. 62 | 63 | 64 | /*************************************************************************************************** 65 | * APPLICATION IMPORTS 66 | */ 67 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /src/theme/variables.scss: -------------------------------------------------------------------------------- 1 | // Ionic Variables and Theming. For more info, please see: 2 | // http://ionicframework.com/docs/theming/ 3 | 4 | /** Ionic CSS Variables **/ 5 | :root { 6 | /** primary **/ 7 | --ion-color-primary: #3880ff; 8 | --ion-color-primary-rgb: 56, 128, 255; 9 | --ion-color-primary-contrast: #ffffff; 10 | --ion-color-primary-contrast-rgb: 255, 255, 255; 11 | --ion-color-primary-shade: #3171e0; 12 | --ion-color-primary-tint: #4c8dff; 13 | 14 | /** secondary **/ 15 | --ion-color-secondary: #3dc2ff; 16 | --ion-color-secondary-rgb: 61, 194, 255; 17 | --ion-color-secondary-contrast: #ffffff; 18 | --ion-color-secondary-contrast-rgb: 255, 255, 255; 19 | --ion-color-secondary-shade: #36abe0; 20 | --ion-color-secondary-tint: #50c8ff; 21 | 22 | /** tertiary **/ 23 | --ion-color-tertiary: #5260ff; 24 | --ion-color-tertiary-rgb: 82, 96, 255; 25 | --ion-color-tertiary-contrast: #ffffff; 26 | --ion-color-tertiary-contrast-rgb: 255, 255, 255; 27 | --ion-color-tertiary-shade: #4854e0; 28 | --ion-color-tertiary-tint: #6370ff; 29 | 30 | /** success **/ 31 | --ion-color-success: #2dd36f; 32 | --ion-color-success-rgb: 45, 211, 111; 33 | --ion-color-success-contrast: #ffffff; 34 | --ion-color-success-contrast-rgb: 255, 255, 255; 35 | --ion-color-success-shade: #28ba62; 36 | --ion-color-success-tint: #42d77d; 37 | 38 | /** warning **/ 39 | --ion-color-warning: #ffc409; 40 | --ion-color-warning-rgb: 255, 196, 9; 41 | --ion-color-warning-contrast: #000000; 42 | --ion-color-warning-contrast-rgb: 0, 0, 0; 43 | --ion-color-warning-shade: #e0ac08; 44 | --ion-color-warning-tint: #ffca22; 45 | 46 | /** danger **/ 47 | --ion-color-danger: #eb445a; 48 | --ion-color-danger-rgb: 235, 68, 90; 49 | --ion-color-danger-contrast: #ffffff; 50 | --ion-color-danger-contrast-rgb: 255, 255, 255; 51 | --ion-color-danger-shade: #cf3c4f; 52 | --ion-color-danger-tint: #ed576b; 53 | 54 | /** dark **/ 55 | --ion-color-dark: #222428; 56 | --ion-color-dark-rgb: 34, 36, 40; 57 | --ion-color-dark-contrast: #ffffff; 58 | --ion-color-dark-contrast-rgb: 255, 255, 255; 59 | --ion-color-dark-shade: #1e2023; 60 | --ion-color-dark-tint: #383a3e; 61 | 62 | /** medium **/ 63 | --ion-color-medium: #92949c; 64 | --ion-color-medium-rgb: 146, 148, 156; 65 | --ion-color-medium-contrast: #ffffff; 66 | --ion-color-medium-contrast-rgb: 255, 255, 255; 67 | --ion-color-medium-shade: #808289; 68 | --ion-color-medium-tint: #9d9fa6; 69 | 70 | /** light **/ 71 | --ion-color-light: #f4f5f8; 72 | --ion-color-light-rgb: 244, 245, 248; 73 | --ion-color-light-contrast: #000000; 74 | --ion-color-light-contrast-rgb: 0, 0, 0; 75 | --ion-color-light-shade: #d7d8da; 76 | --ion-color-light-tint: #f5f6f9; 77 | } 78 | 79 | @media (prefers-color-scheme: dark) { 80 | /* 81 | * Dark Colors 82 | * ------------------------------------------- 83 | */ 84 | 85 | body { 86 | --ion-color-primary: #428cff; 87 | --ion-color-primary-rgb: 66,140,255; 88 | --ion-color-primary-contrast: #ffffff; 89 | --ion-color-primary-contrast-rgb: 255,255,255; 90 | --ion-color-primary-shade: #3a7be0; 91 | --ion-color-primary-tint: #5598ff; 92 | 93 | --ion-color-secondary: #50c8ff; 94 | --ion-color-secondary-rgb: 80,200,255; 95 | --ion-color-secondary-contrast: #ffffff; 96 | --ion-color-secondary-contrast-rgb: 255,255,255; 97 | --ion-color-secondary-shade: #46b0e0; 98 | --ion-color-secondary-tint: #62ceff; 99 | 100 | --ion-color-tertiary: #6a64ff; 101 | --ion-color-tertiary-rgb: 106,100,255; 102 | --ion-color-tertiary-contrast: #ffffff; 103 | --ion-color-tertiary-contrast-rgb: 255,255,255; 104 | --ion-color-tertiary-shade: #5d58e0; 105 | --ion-color-tertiary-tint: #7974ff; 106 | 107 | --ion-color-success: #2fdf75; 108 | --ion-color-success-rgb: 47,223,117; 109 | --ion-color-success-contrast: #000000; 110 | --ion-color-success-contrast-rgb: 0,0,0; 111 | --ion-color-success-shade: #29c467; 112 | --ion-color-success-tint: #44e283; 113 | 114 | --ion-color-warning: #ffd534; 115 | --ion-color-warning-rgb: 255,213,52; 116 | --ion-color-warning-contrast: #000000; 117 | --ion-color-warning-contrast-rgb: 0,0,0; 118 | --ion-color-warning-shade: #e0bb2e; 119 | --ion-color-warning-tint: #ffd948; 120 | 121 | --ion-color-danger: #ff4961; 122 | --ion-color-danger-rgb: 255,73,97; 123 | --ion-color-danger-contrast: #ffffff; 124 | --ion-color-danger-contrast-rgb: 255,255,255; 125 | --ion-color-danger-shade: #e04055; 126 | --ion-color-danger-tint: #ff5b71; 127 | 128 | --ion-color-dark: #f4f5f8; 129 | --ion-color-dark-rgb: 244,245,248; 130 | --ion-color-dark-contrast: #000000; 131 | --ion-color-dark-contrast-rgb: 0,0,0; 132 | --ion-color-dark-shade: #d7d8da; 133 | --ion-color-dark-tint: #f5f6f9; 134 | 135 | --ion-color-medium: #989aa2; 136 | --ion-color-medium-rgb: 152,154,162; 137 | --ion-color-medium-contrast: #000000; 138 | --ion-color-medium-contrast-rgb: 0,0,0; 139 | --ion-color-medium-shade: #86888f; 140 | --ion-color-medium-tint: #a2a4ab; 141 | 142 | --ion-color-light: #222428; 143 | --ion-color-light-rgb: 34,36,40; 144 | --ion-color-light-contrast: #ffffff; 145 | --ion-color-light-contrast-rgb: 255,255,255; 146 | --ion-color-light-shade: #1e2023; 147 | --ion-color-light-tint: #383a3e; 148 | } 149 | 150 | /* 151 | * iOS Dark Theme 152 | * ------------------------------------------- 153 | */ 154 | 155 | .ios body { 156 | --ion-background-color: #000000; 157 | --ion-background-color-rgb: 0,0,0; 158 | 159 | --ion-text-color: #ffffff; 160 | --ion-text-color-rgb: 255,255,255; 161 | 162 | --ion-color-step-50: #0d0d0d; 163 | --ion-color-step-100: #1a1a1a; 164 | --ion-color-step-150: #262626; 165 | --ion-color-step-200: #333333; 166 | --ion-color-step-250: #404040; 167 | --ion-color-step-300: #4d4d4d; 168 | --ion-color-step-350: #595959; 169 | --ion-color-step-400: #666666; 170 | --ion-color-step-450: #737373; 171 | --ion-color-step-500: #808080; 172 | --ion-color-step-550: #8c8c8c; 173 | --ion-color-step-600: #999999; 174 | --ion-color-step-650: #a6a6a6; 175 | --ion-color-step-700: #b3b3b3; 176 | --ion-color-step-750: #bfbfbf; 177 | --ion-color-step-800: #cccccc; 178 | --ion-color-step-850: #d9d9d9; 179 | --ion-color-step-900: #e6e6e6; 180 | --ion-color-step-950: #f2f2f2; 181 | 182 | --ion-toolbar-background: #0d0d0d; 183 | 184 | --ion-item-background: #000000; 185 | } 186 | 187 | 188 | /* 189 | * Material Design Dark Theme 190 | * ------------------------------------------- 191 | */ 192 | 193 | .md body { 194 | --ion-background-color: #121212; 195 | --ion-background-color-rgb: 18,18,18; 196 | 197 | --ion-text-color: #ffffff; 198 | --ion-text-color-rgb: 255,255,255; 199 | 200 | --ion-border-color: #222222; 201 | 202 | --ion-color-step-50: #1e1e1e; 203 | --ion-color-step-100: #2a2a2a; 204 | --ion-color-step-150: #363636; 205 | --ion-color-step-200: #414141; 206 | --ion-color-step-250: #4d4d4d; 207 | --ion-color-step-300: #595959; 208 | --ion-color-step-350: #656565; 209 | --ion-color-step-400: #717171; 210 | --ion-color-step-450: #7d7d7d; 211 | --ion-color-step-500: #898989; 212 | --ion-color-step-550: #949494; 213 | --ion-color-step-600: #a0a0a0; 214 | --ion-color-step-650: #acacac; 215 | --ion-color-step-700: #b8b8b8; 216 | --ion-color-step-750: #c4c4c4; 217 | --ion-color-step-800: #d0d0d0; 218 | --ion-color-step-850: #dbdbdb; 219 | --ion-color-step-900: #e7e7e7; 220 | --ion-color-step-950: #f3f3f3; 221 | 222 | --ion-item-background: #1e1e1e; 223 | 224 | --ion-toolbar-background: #1f1f1f; 225 | 226 | --ion-tab-bar-background: #1f1f1f; 227 | } 228 | } -------------------------------------------------------------------------------- /src/zone-flags.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Prevents Angular change detection from 3 | * running with certain Web Component callbacks 4 | */ 5 | (window as any).__Zone_disable_customElements = true; 6 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "include": [ 8 | "src/**/*.ts" 9 | ], 10 | "exclude": [ 11 | "src/test.ts", 12 | "src/**/*.spec.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "module": "esnext", 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "importHelpers": true, 13 | "target": "es2015", 14 | "typeRoots": [ 15 | "node_modules/@types" 16 | ], 17 | "lib": [ 18 | "es2018", 19 | "dom" 20 | ] 21 | }, 22 | "angularCompilerOptions": { 23 | "fullTemplateTypeCheck": true, 24 | "strictInjectionParameters": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/zone-flags.ts", 13 | "src/polyfills.ts" 14 | ], 15 | "include": [ 16 | "src/**/*.spec.ts", 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rulesDirectory": [ 4 | "codelyzer" 5 | ], 6 | "rules": { 7 | "align": { 8 | "options": [ 9 | "parameters", 10 | "statements" 11 | ] 12 | }, 13 | "array-type": false, 14 | "arrow-parens": false, 15 | "arrow-return-shorthand": true, 16 | "curly": true, 17 | "deprecation": { 18 | "severity": "warn" 19 | }, 20 | "eofline": true, 21 | "import-blacklist": [ 22 | true, 23 | "rxjs/Rx" 24 | ], 25 | "import-spacing": true, 26 | "indent": { 27 | "options": [ 28 | "spaces" 29 | ] 30 | }, 31 | "interface-name": false, 32 | "max-classes-per-file": false, 33 | "max-line-length": [ 34 | true, 35 | 140 36 | ], 37 | "member-access": false, 38 | "member-ordering": [ 39 | true, 40 | { 41 | "order": [ 42 | "static-field", 43 | "instance-field", 44 | "static-method", 45 | "instance-method" 46 | ] 47 | } 48 | ], 49 | "no-consecutive-blank-lines": false, 50 | "no-console": [ 51 | true, 52 | "debug", 53 | "info", 54 | "time", 55 | "timeEnd", 56 | "trace" 57 | ], 58 | "no-empty": false, 59 | "no-inferrable-types": [ 60 | true, 61 | "ignore-params" 62 | ], 63 | "no-non-null-assertion": true, 64 | "no-redundant-jsdoc": true, 65 | "no-switch-case-fall-through": true, 66 | "no-var-requires": false, 67 | "object-literal-key-quotes": [ 68 | true, 69 | "as-needed" 70 | ], 71 | "object-literal-sort-keys": false, 72 | "ordered-imports": false, 73 | "quotemark": [ 74 | true, 75 | "single" 76 | ], 77 | "semicolon": { 78 | "options": [ 79 | "always" 80 | ] 81 | }, 82 | "space-before-function-paren": { 83 | "options": { 84 | "anonymous": "never", 85 | "asyncArrow": "always", 86 | "constructor": "never", 87 | "method": "never", 88 | "named": "never" 89 | } 90 | }, 91 | "trailing-comma": false, 92 | "no-output-on-prefix": true, 93 | "no-inputs-metadata-property": true, 94 | "no-host-metadata-property": true, 95 | "no-input-rename": true, 96 | "no-output-rename": true, 97 | "typedef-whitespace": { 98 | "options": [ 99 | { 100 | "call-signature": "nospace", 101 | "index-signature": "nospace", 102 | "parameter": "nospace", 103 | "property-declaration": "nospace", 104 | "variable-declaration": "nospace" 105 | }, 106 | { 107 | "call-signature": "onespace", 108 | "index-signature": "onespace", 109 | "parameter": "onespace", 110 | "property-declaration": "onespace", 111 | "variable-declaration": "onespace" 112 | } 113 | ] 114 | }, 115 | "use-lifecycle-interface": true, 116 | "use-pipe-transform-interface": true, 117 | "one-variable-per-declaration": false, 118 | "component-class-suffix": [true, "Page", "Component"], 119 | "directive-class-suffix": true, 120 | "directive-selector": [ 121 | true, 122 | "attribute", 123 | "app", 124 | "camelCase" 125 | ], 126 | "component-selector": [ 127 | true, 128 | "element", 129 | "app", 130 | "page", 131 | "kebab-case" 132 | ] 133 | , "variable-name": { 134 | "options": [ 135 | "ban-keywords", 136 | "check-format", 137 | "allow-pascal-case" 138 | ] 139 | }, 140 | "whitespace": { 141 | "options": [ 142 | "check-branch", 143 | "check-decl", 144 | "check-operator", 145 | "check-separator", 146 | "check-type", 147 | "check-typecast" 148 | ] 149 | } 150 | } 151 | } 152 | --------------------------------------------------------------------------------