├── hooks
├── .gitignore
└── README.md
├── www
├── .gitignore
├── templates
│ ├── layout.html
│ └── snaps
│ │ └── stream.html
├── js
│ ├── controllers
│ │ ├── app_ctrl.js
│ │ └── snaps_ctrl.js
│ ├── modules.js
│ ├── app.js
│ └── strftime.js
├── css
│ └── style.css
└── index.html
├── .bowerrc
├── .gitignore
├── ionic.project
├── README.md
├── firebase.json
├── bower.json
├── package.json
├── scss
└── ionic.app.scss
├── config.xml
└── gulpfile.js
/hooks/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/www/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "www/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | www/lib/*
3 | plugins/*
4 | platforms/*
5 | merges/*
6 |
--------------------------------------------------------------------------------
/www/templates/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/ionic.project:
--------------------------------------------------------------------------------
1 | {
2 | "name": "snap",
3 | "email": "brentvatne@gmail.com",
4 | "app_id": "",
5 | "package_name": ""
6 | }
7 |
--------------------------------------------------------------------------------
/www/js/controllers/app_ctrl.js:
--------------------------------------------------------------------------------
1 | angular.module('snap.controllers')
2 | .controller('AppCtrl', function($scope, $state) {
3 | })
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Hey look an image feed! Neato!
2 |
3 | Make this into something like Instagram or Snapchat if you like, as an
4 | exercise!
5 |
--------------------------------------------------------------------------------
/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "firebase": "snap-ruby-db",
3 | "public": "www",
4 | "ignore": [
5 | "firebase.json",
6 | ".*",
7 | "**/node_modules/**"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/www/js/modules.js:
--------------------------------------------------------------------------------
1 | angular.module('snap.controllers', [])
2 | angular.module('snap.services', [])
3 | angular.module('snap.directives', [])
4 | angular.module('snap', ['ionic', 'ngCordova', 'firebase', 'snap.controllers'])
5 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Snap!",
3 | "private": "true",
4 | "devDependencies": {
5 | "ionic": "driftyco/ionic-bower#1.0.0-beta.8"
6 | },
7 | "dependencies": {
8 | "angular-local-storage": "~0.0.5",
9 | "ngCordova": "~0.1.2-alpha",
10 | "angularfire": "~0.7.1",
11 | "firebase": "~1.0.17"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ionic-project",
3 | "version": "1.0.0",
4 | "description": "An Ionic project",
5 | "dependencies": {
6 | "gulp": "^3.5.6",
7 | "gulp-sass": "^0.7.1",
8 | "gulp-concat": "^2.2.0",
9 | "gulp-minify-css": "^0.3.0",
10 | "gulp-rename": "^1.2.0"
11 | },
12 | "devDependencies": {
13 | "bower": "^1.3.3",
14 | "gulp-util": "^2.2.14",
15 | "shelljs": "^0.3.0"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/www/templates/snaps/stream.html:
--------------------------------------------------------------------------------
1 |
2 | Snaps!
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
![]()
16 |
17 |
18 | {{formattedDate(snap.created)}}
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/scss/ionic.app.scss:
--------------------------------------------------------------------------------
1 | /*
2 | To customize the look and feel of Ionic, you can override the variables
3 | in ionic's _variables.scss file.
4 |
5 | For example, you might change some of the default colors:
6 |
7 | $light: #fff !default;
8 | $stable: #f8f8f8 !default;
9 | $positive: #4a87ee !default;
10 | $calm: #43cee6 !default;
11 | $balanced: #66cc33 !default;
12 | $energized: #f0b840 !default;
13 | $assertive: #ef4e3a !default;
14 | $royal: #8a6de9 !default;
15 | $dark: #444 !default;
16 | */
17 |
18 | // The path for our ionicons font files, relative to the built CSS in www/css
19 | $ionicons-font-path: "../lib/ionic/fonts" !default;
20 |
21 | // Include all of Ionic
22 | @import "www/lib/ionic/scss/ionic";
23 |
24 |
--------------------------------------------------------------------------------
/www/js/app.js:
--------------------------------------------------------------------------------
1 | angular.module('snap')
2 | .constant('FirebaseUrl', "https://snap-ruby-db.firebaseio.com")
3 |
4 | .run(function($ionicPlatform) {
5 | $ionicPlatform.ready(function() {
6 | // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
7 | // for form inputs)
8 | if(window.cordova && window.cordova.plugins.Keyboard) {
9 | cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
10 | }
11 | if(window.StatusBar) {
12 | // org.apache.cordova.statusbar required
13 | StatusBar.styleDefault();
14 | }
15 | });
16 | })
17 |
18 | .config(function($stateProvider, $urlRouterProvider) {
19 | $stateProvider
20 | .state('snaps', {
21 | url: "/snaps",
22 | abstract: true,
23 | templateUrl: "templates/layout.html"
24 | })
25 |
26 | .state('snaps.stream', {
27 | url: "/stream",
28 | templateUrl: 'templates/snaps/stream.html',
29 | controller: 'SnapsCtrl'
30 | })
31 |
32 | $urlRouterProvider.otherwise('/snaps/stream');
33 | });
34 |
--------------------------------------------------------------------------------
/www/css/style.css:
--------------------------------------------------------------------------------
1 | /* Empty. Add your own CSS if you like */
2 |
3 | .loading-spinner {
4 | font-size: 30px;
5 | color: #ccc;
6 | }
7 |
8 | .loading-wrapper {
9 | text-align: center;
10 | padding-top: 40px;
11 | }
12 |
13 | @media all and (min-width: 600px) {
14 | .card {
15 | width: 48%;
16 | display: inline-block;
17 | vertical-align: top;
18 | margin: 0;
19 | margin-left: 12px;
20 | margin-top: 10px;
21 | }
22 |
23 | .list {
24 | padding-top: 25px;
25 | }
26 | }
27 |
28 | .bar-header {
29 | height: 54px;
30 | }
31 |
32 | .list {
33 | text-align: center;
34 | }
35 |
36 | .bar-header .title {
37 | line-height: 54px;
38 | font-size: 20px;
39 | padding-left: 10px;
40 | }
41 |
42 | .bar-header .button {
43 | border: none;
44 | font-size: 20px;
45 | }
46 |
47 | .bar .button.button-icon:before, .bar .button .icon:before, .bar .button.icon:before, .bar .button.icon-left:before, .bar .button.icon-right:before {
48 | font-size: 25px;
49 | }
50 |
51 | .platform-browser .camera-button {
52 | display: none;
53 | }
54 |
--------------------------------------------------------------------------------
/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Snap!
4 |
5 | Snap!
6 |
7 |
8 | Brent
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Snaps!
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var gutil = require('gulp-util');
3 | var bower = require('bower');
4 | var concat = require('gulp-concat');
5 | var sass = require('gulp-sass');
6 | var minifyCss = require('gulp-minify-css');
7 | var rename = require('gulp-rename');
8 | var sh = require('shelljs');
9 |
10 | var paths = {
11 | sass: ['./scss/**/*.scss']
12 | };
13 |
14 | gulp.task('default', ['sass']);
15 |
16 | gulp.task('sass', function(done) {
17 | gulp.src('./scss/ionic.app.scss')
18 | .pipe(sass())
19 | .pipe(gulp.dest('./www/css/'))
20 | .pipe(minifyCss({
21 | keepSpecialComments: 0
22 | }))
23 | .pipe(rename({ extname: '.min.css' }))
24 | .pipe(gulp.dest('./www/css/'))
25 | .on('end', done);
26 | });
27 |
28 | gulp.task('watch', function() {
29 | gulp.watch(paths.sass, ['sass']);
30 | });
31 |
32 | gulp.task('install', ['git-check'], function() {
33 | return bower.commands.install()
34 | .on('log', function(data) {
35 | gutil.log('bower', gutil.colors.cyan(data.id), data.message);
36 | });
37 | });
38 |
39 | gulp.task('git-check', function(done) {
40 | if (!sh.which('git')) {
41 | console.log(
42 | ' ' + gutil.colors.red('Git is not installed.'),
43 | '\n Git, the version control system, is required to download Ionic.',
44 | '\n Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
45 | '\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
46 | );
47 | process.exit(1);
48 | }
49 | done();
50 | });
51 |
--------------------------------------------------------------------------------
/www/js/controllers/snaps_ctrl.js:
--------------------------------------------------------------------------------
1 | angular.module('snap.controllers')
2 | .controller('SnapsCtrl', function($scope, $rootScope, $state, $ionicLoading,
3 | $cordovaDialogs, $cordovaVibration,
4 | $cordovaCamera, FirebaseUrl, $firebase) {
5 |
6 | $scope.isLoading = true;
7 | var snapsRef = new Firebase(FirebaseUrl + "/snaps");
8 | $scope.snaps = $firebase(snapsRef);
9 | $scope.snaps.$on('loaded', function() {
10 | $scope.isLoading = false;
11 | });
12 |
13 | $scope.formattedDate = function(dateInteger) {
14 | return strftime('%B %d, %Y %H:%M:%S', new Date(dateInteger));
15 | }
16 |
17 | $scope.takePicture = function() {
18 | var options = {
19 | quality : 75,
20 | destinationType : Camera.DestinationType.DATA_URL,
21 | sourceType : Camera.PictureSourceType.CAMERA,
22 | allowEdit : true,
23 | encodingType: Camera.EncodingType.JPEG,
24 | targetWidth: 600,
25 | targetHeight: 600,
26 | popoverOptions: CameraPopoverOptions,
27 | saveToPhotoAlbum: false
28 | };
29 |
30 | $cordovaCamera.getPicture(options).then(function(imageData) {
31 | $ionicLoading.show({
32 | template: 'Uploading...'
33 | });
34 |
35 | $scope.snaps.$add({data: imageData, created: (new Date().getTime())}).
36 | then(function(data) {
37 | $ionicLoading.hide();
38 | });
39 | }, function(err) {
40 | // If you cancel or there is an error for some reason,
41 | // it goes here.
42 | });
43 | }
44 | });
45 |
--------------------------------------------------------------------------------
/hooks/README.md:
--------------------------------------------------------------------------------
1 |
21 | # Cordova Hooks
22 |
23 | This directory may contain scripts used to customize cordova commands. This
24 | directory used to exist at `.cordova/hooks`, but has now been moved to the
25 | project root. Any scripts you add to these directories will be executed before
26 | and after the commands corresponding to the directory name. Useful for
27 | integrating your own build systems or integrating with version control systems.
28 |
29 | __Remember__: Make your scripts executable.
30 |
31 | ## Hook Directories
32 | The following subdirectories will be used for hooks:
33 |
34 | after_build/
35 | after_compile/
36 | after_docs/
37 | after_emulate/
38 | after_platform_add/
39 | after_platform_rm/
40 | after_platform_ls/
41 | after_plugin_add/
42 | after_plugin_ls/
43 | after_plugin_rm/
44 | after_plugin_search/
45 | after_prepare/
46 | after_run/
47 | after_serve/
48 | before_build/
49 | before_compile/
50 | before_docs/
51 | before_emulate/
52 | before_platform_add/
53 | before_platform_rm/
54 | before_platform_ls/
55 | before_plugin_add/
56 | before_plugin_ls/
57 | before_plugin_rm/
58 | before_plugin_search/
59 | before_prepare/
60 | before_run/
61 | before_serve/
62 | pre_package/ <-- Windows 8 and Windows Phone only.
63 |
64 | ## Script Interface
65 |
66 | All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:
67 |
68 | * CORDOVA_VERSION - The version of the Cordova-CLI.
69 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
70 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
71 | * CORDOVA_HOOK - Path to the hook that is being executed.
72 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)
73 |
74 | If a script returns a non-zero exit code, then the parent cordova command will be aborted.
75 |
76 |
77 | ## Writing hooks
78 |
79 | We highly recommend writting your hooks using Node.js so that they are
80 | cross-platform. Some good examples are shown here:
81 |
82 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)
83 |
84 |
--------------------------------------------------------------------------------
/www/js/strftime.js:
--------------------------------------------------------------------------------
1 | (function(){function i(c,a,b){return g(c,a,b)}function g(c,a,b,j){j=j||{};a&&!n(a)&&(b=a,a=void 0);a=a||new Date;b=b||o;b.formats=b.formats||{};var i=a.getTime(),h=j.timezone,e=typeof h;if(j.utc||e=="number"||e=="string")a=p(a);if(h){if(e=="string")var k=h[0]=="-"?-1:1,q=parseInt(h.slice(1,3),10),r=parseInt(h.slice(3,5),10),h=k*(60*q+r);e&&(a=new Date(a.getTime()+h*6E4))}return c.replace(/%([-_0]?.)/g,function(c,e){var d;if(e.length==2){d=e[0];if(d=="-")d="";else if(d=="_")d=" ";else if(d=="0")d=
2 | "0";else return c;e=e[1]}switch(e){case "A":return b.days[a.getDay()];case "a":return b.shortDays[a.getDay()];case "B":return b.months[a.getMonth()];case "b":return b.shortMonths[a.getMonth()];case "C":return f(Math.floor(a.getFullYear()/100),d);case "D":return g(b.formats.D||"%m/%d/%y",a,b);case "d":return f(a.getDate(),d);case "e":return a.getDate();case "F":return g(b.formats.F||"%Y-%m-%d",a,b);case "H":return f(a.getHours(),d);case "h":return b.shortMonths[a.getMonth()];case "I":return f(l(a),
3 | d);case "j":return d=new Date(a.getFullYear(),0,1),d=Math.ceil((a.getTime()-d.getTime())/864E5),f(d,3);case "k":return f(a.getHours(),d==null?" ":d);case "L":return f(Math.floor(i%1E3),3);case "l":return f(l(a),d==null?" ":d);case "M":return f(a.getMinutes(),d);case "m":return f(a.getMonth()+1,d);case "n":return"\n";case "o":return String(a.getDate())+s(a.getDate());case "P":return a.getHours()<12?b.am:b.pm;case "p":return a.getHours()<12?b.AM:b.PM;case "R":return g(b.formats.R||"%H:%M",a,b);case "r":return g(b.formats.r||
4 | "%I:%M:%S %p",a,b);case "S":return f(a.getSeconds(),d);case "s":return Math.floor(i/1E3);case "T":return g(b.formats.T||"%H:%M:%S",a,b);case "t":return"\t";case "U":return f(m(a,"sunday"),d);case "u":return d=a.getDay(),d==0?7:d;case "v":return g(b.formats.v||"%e-%b-%Y",a,b);case "W":return f(m(a,"monday"),d);case "w":return a.getDay();case "Y":return a.getFullYear();case "y":return d=String(a.getFullYear()),d.slice(d.length-2);case "Z":return j.utc?"GMT":(d=a.toString().match(/\(([\w\s]+)\)/))&&
5 | d[1]||"";case "z":return j.utc?"+0000":(d=typeof h=="number"?h:-a.getTimezoneOffset(),(d<0?"-":"+")+f(Math.floor(Math.abs(d)/60))+f(Math.abs(d)%60));default:return e}})}function p(c){var a=(c.getTimezoneOffset()||0)*6E4;return new Date(c.getTime()+a)}function n(c){for(var a=0,b=k.length,a=0;a12&&(c-=12);return c}function s(c){var a=c%10;c%=100;if(c>=11&&c<=13||a===0||a>=4)return"th";switch(a){case 1:return"st";case 2:return"nd";case 3:return"rd"}}function m(c,a){var a=a||"sunday",b=c.getDay();a=="monday"&&(b==0?b=6:b--);var e=new Date(c.getFullYear(),0,1);return Math.floor(((c-e)/864E5+7-b)/7)}var e;e=typeof module!=="undefined"?module.exports=i:function(){return this||(0,eval)("this")}();var o={days:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),shortDays:"Sun Mon Tue Wed Thu Fri Sat".split(" "),
7 | months:"January February March April May June July August September October November December".split(" "),shortMonths:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),AM:"AM",PM:"PM",am:"am",pm:"pm"};e.strftime=i;e.strftimeTZ=i.strftimeTZ=function(c,a,b,e){if((typeof b=="number"||typeof b=="string")&&e==null)e=b,b=void 0;return g(c,a,b,{timezone:e})};e.strftimeUTC=i.strftimeUTC=function(c,a,b){return g(c,a,b,{utc:!0})};e.localizedStrftime=i.localizedStrftime=function(c){return function(a,
8 | b){return g(a,b,c)}};var k=["getTime","getTimezoneOffset","getDay","getDate","getMonth","getFullYear","getYear","getHours","getMinutes","getSeconds"]})();
9 |
--------------------------------------------------------------------------------