Taking a series of photos in one view, display them all in the next

Hello! So here is the gist of what I’m trying to do.

short version: what is wrong with
template.html

ng-src={{photo}}

and

app.js

$scope.photo = file:///storage/emulated/0/Android/data/com.ionicframework.hourglasssimple410460/cache/1428009011219.jpg;  

(or something like that?)

view 1 “setup” - set settings that determine the rate of photo-taking (similar to timelapse)
view 2 “takePhotos” - open and close camera app when appropriate & ask user to take a photo
view 3 “selectPhotos” - display all of the images

that’s all I’m trying to do (for now). presently, everything works, except that none of the images are showing up as expected in view 3 .

GITHUB repo HERE

relevant stuff here:

app.js

// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('starter', ['ionic', 'ngCordova', 'starter.services', 'myFactory'])

  .run(function($ionicPlatform) {
    $ionicPlatform.ready(function() {
      // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
      // for form inputs)
      if(window.cordova && window.cordova.plugins.Keyboard) {
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      }
      if(window.StatusBar) {
        StatusBar.styleDefault();
      }
    });
  })

  .config(function($stateProvider, $urlRouterProvider, $compileProvider) {

    // honestly not sure what this does. probably something to make sure that the image is legible angular
    $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);

    $stateProvider

    // what the state is called
    .state('takePhoto', {
      // the url that can be accessed via href propertiess
      url: '/takePhoto',
      // the path to view the template html file
      templateUrl: 'templates/takePhoto.html',
      // the controller to be used in this view
      controller: 'PhotoCtrl'
      })

    .state('setup', {
      url: '/setup',
      templateUrl: 'templates/setup.html',
      controller: 'MainCtrl'
    })

    .state('selectPhoto', {
      url: '/selectPhoto',
      templateUrl: 'templates/selectPhoto.html',
      controller: 'SelectCtrl'
    })

    $urlRouterProvider.otherwise('/setup')

    // function($compileProvider){
    //   $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);
    // }
  })

  // controller for the settings page
  .controller('MainCtrl', function($scope, Camera, $localstorage) {
    console.log("using the 'MainCtrl' controller");

    // basically initializing them to 60 and 10, if the user has old settings
    // it will remember them
    $scope.durVal = $localstorage.get('durVal',60);
    $scope.freqVal =  $localstorage.get('freqVal',10);

    $scope.setSettings = function(newDurVal, newFreqVal){

        //clear local storage
        localStorage.clear();

        // This sets durVal and freqVal equal to the newDurVal and newFreqVal that we passed in
        $localstorage.set('durVal',newDurVal);
        $localstorage.set('freqVal',newFreqVal);

        // This does two things, it defines our scope's durVal & freqVal based on what's in the local storage
        // and if it doesn't find anything, it reverts to those default values
        $scope.durVal = $localstorage.get('durVal',60);
        $scope.freqVal =  $localstorage.get('freqVal',10)
        
        // log the inputs that are passed in
        console.log('passed in DurVal ' + newDurVal);
        console.log('passed in FreqVal ' + newFreqVal);

        // log what we can read from the local storage
        console.log('durVal ' + $localstorage.get('durVal','durVal undefined'));
        console.log('freqVal '+ $localstorage.get('freqVal','freqVal undefined'));
    };
  })

  //this is the controller for taking photos
  .controller('PhotoCtrl', function(Camera, $scope, $localstorage, $timeout, $interval, $location) {
    console.log("using the 'PhotoCtrl' controller");

    $scope.durVal = $localstorage.get('durVal',60);
    $scope.freqVal =  $localstorage.get('freqVal',10);

    //the amount of photos we want to take
    $scope.photosCount = parseInt($scope.durVal / $scope.freqVal);
    $localstorage.set('photosCount', $scope.photosCount);
    //the amount of photos we have taken so far
    $scope.photosTaken = 0;

    // print them out for sanity
    console.log('duration:            ' + $scope.durVal);
    console.log('frequency:           ' + $scope.freqVal);
    console.log('expecting x photos:  ' + $scope.photosCount);
    
    // ask user to take a photo every frequency * 60 seconds/ minute * 1000 millis/second
    $interval( function(){ $scope.callAtInterval(); }, $scope.freqVal*60000);

    $scope.callAtInterval = function() {
      //if the amount of photos we've taken is less than the amount we are going to take
      if( $scope.photosTaken < $scope.photosCount)
      { 
        //console message to let me know that an interval occurred
        //console.log("$scope.callAtInterval - Interval occurred");

        //declare a variable, whose name is photoN where N = the photo number
        //define this variable as equal to the number of photos taken (for now)
        //$localstorage.set('photo' + $scope.photosTaken, $scope.photosTaken);

        //get a photo, and pass it the name of the variable that we want to give the imageURI
        $scope.getPhoto("photo" + $scope.photosTaken);

        // log to see if the variable here is in fact what we expect it to be
        //console.log("variable photo" + $scope.photosTaken + " is equal to " + $localstorage.get("photo" + $scope.photosTaken , 'undefined') );

        // confirm that the variable has actually been changed
        console.log("I think you've taken " + $scope.photosTaken + " photos" );
      }
    }

    // every three seconds, call function
    $timeout( function(){ $scope.callAtTimeout(); }, $scope.durVal*60000);

    // this function doesn't do anything except for console.log
    $scope.callAtTimeout = function() {
        console.log("$scope.callAtInterval - Timeout occurred");
        $location.url('/selectPhoto');
    }

    $scope.getPhoto = function(imageName) {
      Camera.getPicture().then(function(imageURI) {

        //set the name of the image (something like photo1) equal to whatever imageURI is
        $localstorage.set(imageName,imageURI);

        //print out the imageURI
        console.log("saved: " + imageName + " = " + imageURI);

        //register that we just took an image
        $scope.photosTaken++;

      }, function(err) {
        console.err(err);
      }, {
        quality: 75,
        targetWidth: 320,
        targetHeight: 320,
        saveToPhotoAlbum: false
      });
      
    };
  })

  //this is the controller for selecting photos
  .controller('SelectCtrl', function($scope, Camera, $localstorage) {
    $scope.durVal = $localstorage.get('durVal',60);
    $scope.freqVal =  $localstorage.get('freqVal',10);
    $scope.photosCount =  $localstorage.get('photosCount',10);

    $scope.photo0 =  $localstorage.get('photo0');
    $scope.photo1 =  $localstorage.get('photo1');
    $scope.photo2 =  $localstorage.get('photo2');
    $scope.photo3 =  $localstorage.get('photo3');
    $scope.photo4 =  $localstorage.get('photo4');
    $scope.photo5 =  $localstorage.get('photo5');
    $scope.photo6 =  $localstorage.get('photo6');
    $scope.photo7 =  $localstorage.get('photo7');
    $scope.photo8 =  $localstorage.get('photo8');
    $scope.photo9 =  $localstorage.get('photo9');
    $scope.photo10 = $localstorage.get('photo10');
    $scope.photo11 = $localstorage.get('photo11');
    $scope.photo12 = $localstorage.get('photo12');
    $scope.photo13 = $localstorage.get('photo13');
    $scope.photo14 = $localstorage.get('photo14');
    $scope.photo15 = $localstorage.get('photo15');
    $scope.photo16 = $localstorage.get('photo16');
    $scope.photo17 = $localstorage.get('photo17');

    console.log($scope.photo0);
    console.log($scope.photo1);
    console.log($scope.photo2);
    console.log($scope.photo3);
    console.log($scope.photo4);
  });

templates:

setup.html

<ion-view view-title="setup">
  <ion-header-bar class="bar-stable">
    <h1 class="title">setup</h1>
  </ion-header-bar>
  <ion-content>
    <center>
    <img src="img/hourglassSetup.svg" width = 300 id="hourglassSetup"></img>
    </center>
    <div class="list">
	  <div class="item range range-positive">
	    <i class="icon ion-clock"></i>
	    <p class="sideMenuLabel">duration</p>
      <!-- for realsies  duration-->
	    <!-- <input id = "duration" type="range" name="volume" min="30" max="120" value="{{durVal}}" step="{{freqVal}}" ng-model="durVal"> -->

      <!-- for debugging, these values are much smaller than the above -->
      <input id = "duration" type="range" name="volume" min="1" max="5" value="{{durVal}}" step="{{freqVal}}" ng-model="durVal">


	    <p id="sliderValue">{{durVal}} min</p>
	  </div>
	  <div class="item range range-positive">
	    <i class="icon ion-speedometer"></i>
	    <p class="sideMenuLabel">frequency</p>
      <!-- for realsies  frequency-->
	    <!-- <input id = "frequency" type="range" name="volume" min="2" max="15" value="{{freqVal}}" step="1" ng-model="freqVal"> -->

      <!-- for debugging, these values are much smaller than the above -->
      <input id = "frequency" type="range" name="volume" min=".1" max="5" value="{{freqVal}}" step=".1" ng-model="freqVal">

	    <p id="sliderValue">{{freqVal}} min</p>
	  </div>
	  <div class="item item-button-right">
    	<p>
        <a class="button icon icon-right ion-chevron-right" ui-sref="takePhoto" ng-click="setSettings(durVal,freqVal)">start</a>
      </p>
  	</div>
	</div>
  </ion-content>
</ion-view>

takePhoto:

<!-- This is the template for taking a photo -->

<ion-view title="takePhoto">
	<ion-header-bar class="bar-stable">
		<h1 class="title">Photo</h1>
	</ion-header-bar>
	<ion-content padding="true">
		<center>
			<img height=270 src="img/glassGIF2.gif" style="position: absolute; top: 30px;"/>
	  		<img src="img/glassGIF.gif" style="position: relative; top: 0; left: 0;"/>
		    <p ng-model="photosTaken">{{photosTaken}}</p><p ng-model="photosCount">/ {{photosCount}}</p>
	    </center>
	</ion-content>
</ion-view>

selectPhoto.html:

<!-- This is the template for selecting a photo to tweet-->

<ion-view title="selectPhoto">
	<ion-header-bar class="bar-stable">
		<h1 class="title">image selection</h1>
	</ion-header-bar>
	<ion-content padding="true">
	    <p>image selection happens here</p>
	    <img class="choosePhoto" id="photo0"  ng-src="{{photo0}}"></img>
	    <img class="choosePhoto" id="photo1"  ng-src="{{photo1}}"></img>
	    <img class="choosePhoto" id="photo2"  ng-src="{{photo2}}"></img>
	    <img class="choosePhoto" id="photo3"  ng-src="{{photo3}}"></img>
	    <img class="choosePhoto" id="photo4"  ng-src="{{photo4}}"></img>
	    <img class="choosePhoto" id="photo5"  ng-src="{{photo5}}"></img>
	    <img class="choosePhoto" id="photo6"  ng-src="{{photo6}}"></img>
	    <img class="choosePhoto" id="photo7"  ng-src="{{photo7}}"></img>
	    <img class="choosePhoto" id="photo8"  ng-src="{{photo8}}"></img>
	    <img class="choosePhoto" id="photo9"  ng-src="{{photo9}}"></img>
	    <img class="choosePhoto" id="photo10" ng-src="{{photo10}}"></img>
	    <img class="choosePhoto" id="photo11" ng-src="{{photo11}}"></img>
	    <img class="choosePhoto" id="photo12" ng-src="{{photo12}}"></img>
	    <img class="choosePhoto" id="photo13" ng-src="{{photo13}}"></img>
	    <img class="choosePhoto" id="photo14" ng-src="{{photo14}}"></img>
	    <img class="choosePhoto" id="photo15" ng-src="{{photo15}}"></img>
	    <img class="choosePhoto" id="photo16" ng-src="{{photo16}}"></img>
	    <img class="choosePhoto" id="photo17" ng-src="{{photo17}}"></img>
	</ion-content>
</ion-view>

here’s what my logs look like:

0     947082   log      using the 'MainCtrl' controller
1     950497   log      passed in DurVal 1.6
2     950498   log      passed in FreqVal 0.3
3     950498   log      durVal 1.6
4     950499   log      freqVal 0.3
5     950555   log      using the 'PhotoCtrl' controller
6     950557   log      duration:            1.6
7     950558   log      frequency:           0.3
8     950559   log      expecting x photos:  5
9     968660   log      I think you've taken 0 photos
10    978424   log      saved: photo0 = file:///storage/emulated/0/Android/data/com.ionicframework.hourglasssimple410460/cache/1428008977682.jpg
11    986584   log      I think you've taken 1 photos
12    994487   log      saved: photo1 = file:///storage/emulated/0/Android/data/com.ionicframework.hourglasssimple410460/cache/1428008993708.jpg
13    004582   log      I think you've taken 2 photos
14    011970   log      saved: photo2 = file:///storage/emulated/0/Android/data/com.ionicframework.hourglasssimple410460/cache/1428009011219.jpg

bump

please help!

I would really appreciate it.

i cloned your repo, $localstorage.get(‘photo7’) is undefined.
i can’t find the code piece where the photo is actually set to localStorage in services.js
line 120 is unavailable right now.

Hi!

Thanks for helping out. The $localstorage.set happens in app.js line 146

Would really appreciate some help here! Still can’t figure it out.

question

where does imageName come from?

$scope.getPhoto = function(imageName) {

i assume imageName is undefined everytime.

app.js 123

This might be something that I don’t understand about javascript, but I thought it didn’t need to be “declared” when it’s passed into the function like that.

getPhoto is called from the template (takePhoto.html), when a user takes a picture.
thats the moment a user takes a picture and its stored to the localstorage. isnt it?
in this moment imageName is always undefined.

the interval in line 123 is only called every 10minutes, so this is not the usual case. and i dont know where it is for.
i suggest to write unit tests, this will help you.

(http://www.smashingmagazine.com/2014/10/07/introduction-to-unit-testing-in-angularjs/)

I don’t think that takePhoto is ever called from the template. It’s called from the Interval in app.js line 109.

$scope.getPhoto = function(imageName) {

  var options = {
    quality: 75,
    targetWidth: 320,
    targetHeight: 320,
    saveToPhotoAlbum: false
  };

  Camera.getPicture(options).then(function(imageURI) {

    //set the name of the image (something like photo1) equal to whatever imageURI is
    $localstorage.set(imageName,imageURI);

    //print out the imageURI
    console.log("saved: " + imageName + " = " + $localstorage.get(imageName,'undefined'));

    //register that we just took an image
    $scope.photosTaken++;

  }, function(err) {
    console.err(err);
  });

};

all the stuff that uses imageName is inside of the function that (maybe I don’t understand this) defines it. right?

sorry, that button on takePhoto.html is misleading. It shouldn’t do anything. I’ve taken it out to reflect that. (it was a remnant from earlier debugging)

I’ll check out the unit testing article. Thank you for sharing it. My strategy for testing was to get the first two controllers to work with setting strings in the local storage, and then just change that string to the imageURI.

to reiterate, I only want the camera to pop up once every “freqVal” seconds. It’s kind of similar to a timelapse type effect.

I just realized that although in the “select image” view there are a bunch of those 100x100 placeholder images, those are only the photos that weren’t taken during “takePhotos”.

In other words, The localstorage stuff is all working fine, the only problem is that the imageURI isn’t working for some reason. For some reason, "file:///storage/emulated/0/Android/data/com.ionicframework.hourglasssimple410460/cache/1428265485927.jpg" is incompatible with ng-src

I’m already whitelisting with this

$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|file|blob|cdvfile|content):|data:image\//);

which seems to be the usual source of that kind of problem.

bump.

help please!

I’m really stumped on this one. :sweat: :weary:

I’m running in a similar issue. Did you have any change to figure a solution out ?

Same issue happening with me. I can not display images.

hey bro. Didi you fix this? having the same error…

did you fix this?

help please

i am also facing this kind of problem… I gues it is because the image uri is not originally from the mobile file system… You can see that the uri has ionicframework data in it? Is this the cause of not displaying the image in app??

did u solve this?..

i solve this by adding timeout when you pass the file_uri to scope… i don’t know why it works if it has a timeout…

did you ever figure out where to put that whitelist. running into a similar issue on iOS