$cordovaFile not going well with cache of Ionic resulting in showing wrong picture


#1

Following scenario

  1. going to main.admin.emergencyDetail.photos
  2. loading every image and showing as list view
  3. clicking one image in the list opens a modal which enables with ionic slider to slide through the image list
  4. going back to main.admin.emergencyDetail
  5. going back to main.admin and choosing a new emergency from a list (going to another main.admin.emergencyDetail.photos
  6. opening a photo from the list to show in modal: Now the old pictures from last time being on this view showing and from now on only those loaded from point 3. are showing in every main.admin.emergencyDetail.photos state
  7. closing app and reopening enables me to reset this bug. as soon i am on point 3. it takes again this image i opened now in every main.admin.emergencyDetail.photos state

The funny thing is: when I inspected the filesystem file:///data/data/<appname>/cache then the photoCache folder got deleted successfully by going back one state (as I do in 4.) deleting it successfully which means the old picture is cached somehow by ionic. I think I can put somewhere window.cache.clear() but am not quite sure where to…

'use strict';
angular.module('main')
.controller('AdminEmergencyCtrl', function (Action, $window, $state, $ionicSideMenuDelegate,
                                          $location, $rootScope, $ionicHistory, $timeout,
                                          Rest, $stateParams, $log, uiGmapGoogleMapApi,
                                          $mdToast, $ionicPopup, $ionicModal, $scope,
                                          $ionicSlideBoxDelegate, $cordovaFile, $q) {
// Authenticate
($rootScope.authenticated.state &&
$rootScope.authenticated.type === 'Admin') ? '' : $location.url('main/inactive');

$log.log('Hello from your Controller: AdminEmergencyCtrl in module main:. This is your controller:', this);

// Settings
$rootScope.$broadcast('checkMenuButton', {});
$ionicSideMenuDelegate.canDragContent(true);
$scope.$on('$ionicView.leave', function (scopes, states) {
  document.addEventListener('deviceready', function () {
    $cordovaFile.removeRecursively(cordova.file.cacheDirectory, 'photoCache')
      .then(function (success) {
        $log.log('($ionicView.leave) cacheDirectory/photoCache cleared');
      }, function (error) {
        $log.log('($ionicView.leave) cacheDirectory/photoCache clearing error:');
        $log.log(error);
      });
  }, false);
});

// Initialize values
var ctrl = this;
ctrl.emergency = {};

ctrl.currentUser = Action.getDeviceID();
ctrl.map = {};
ctrl.showMap = ($ionicHistory.currentStateName() === 'main.admin.emergencyDetail');
$scope.$on('$ionicView.enter', function (scopes, sates) {
  // reassign boolean to prevent strange loading behaviour of google maps
  ctrl.showMap = ($ionicHistory.currentStateName() === 'main.admin.emergencyDetail');
});
ctrl.assigned = null;

ctrl.hasImages = false;
ctrl.isLoading = true;
$scope.images = [];
ctrl.marker = {};

// Functions declarations
ctrl.getEmergency = function () {
  Rest.getEmergency($stateParams.id,
    function (success) {
      var data = angular.fromJson(success);
      var lat = data.Lat;
      var long = data.Long;
      ctrl.emergency = data;
      ctrl.assigned = data.HandledByID;
      ctrl.map = {center: {latitude: lat, longitude: long}, zoom: 15};
      ctrl.marker = {
        id: 0,
        coords: {latitude: lat, longitude: long}
      };
      ctrl.showMap = true;
    },
    function (error) {
      $log.log(error);
    });
};

/**
 * Folder creating -> Files creating -> writing in files -> returning promise for further handling
 *
 * @returns {Promise}
 */
ctrl.fillTempFolder = function () {
  return $q(function (resolve, reject) {
    resolve(fillTempFolderSuccess());
  });
};

function fillTempFolderSuccess () {
  $log.log('AM IN ctrl.fillTempFolder');
  document.addEventListener('deviceready', function () {
    $cordovaFile.createDir(cordova.file.cacheDirectory, 'photoCache', true)
      .then(function (success) {
        $log.log('AM IN $cordovaFile.createDir');
        $scope.images.forEach(function (item) {
          var blob = new Blob([Action.convertDataURIToBinary(item.src)], {type: 'image/jpg'});
          $cordovaFile.createFile(cordova.file.cacheDirectory + 'photoCache/', item.name, true).then(
            function (success) {
              $log.log('(CREATE FILE) Success');
              $cordovaFile.writeFile(cordova.file.cacheDirectory + 'photoCache/', item.name, blob, true)
                .then(function (success) {
                  $log.log('(WRITE FILE) Success');
                }, function (error) {
                  $log.log('(WRITE FILE) Error');
                  $log.log(error);
                });
            },
            function (error) {
              $log.log('(CREATE FILE) Error');
              $log.log(error);
            }
          );
        });
      }, function (error) {
        $log.log('(CREATE DIR) Could not write to FileSystem');
      });
  }, false);
}

ctrl.loadPictures = function (lastPic) {
  Rest.getNextPicture($stateParams.id, lastPic,
    function (success) {
      var data = angular.fromJson(success);
      var item = {src: 'data:image/jpg;base64,' + data.Data, name: data.Pic};
      $scope.images.push(item);
      $log.log('pic loaded: ' + data.Pic);
      ctrl.hasImages = true;
      ctrl.loadPictures(data.Pic);
    },
    function (error) {
      ctrl.isLoading = false;
      $log.log(cordova.file.cacheDirectory + 'photoCache/');
      ctrl.fillTempFolder().then(function (success) {
        $timeout(function () {
          $log.log('CREATING MODAL');
          $scope.modal = $ionicModal.fromTemplate(
            '<div class="modal image-modal transparent" ng-click="closeModal()">' +
            '<ion-slide-box on-slide-changed="slideChanged(index)" show-pager="false">' +
            '<ion-slide ng-repeat="oImage in images">' +
            '<img ng-src="' + cordova.file.cacheDirectory + 'photoCache/{{oImage.name}}" class="fullscreen-image" />' +
            '</ion-slide>' +
            '</ion-slide-box>' +
            '</div>', {
              scope: $scope,
              animation: 'slide-in-up'
            });
        }, 3000);
      });
    }
  );
};

ctrl.showPicturesPage = function () {
  $state.go('main.admin.emergencyDetail.photos', {'id': $stateParams.id});
};

$scope.openModal = function () {
  $ionicSlideBoxDelegate.slide(0);
  $scope.modal.show();
};

$scope.closeModal = function () {
  $scope.modal.hide();
};

// Called each time the slide changes
$scope.slideChanged = function (index) {
  $scope.slideIndex = index;
};

// Cleanup the modal when we're done with it!
$scope.$on('$destroy', function () {
  $scope.modal.remove();
});

// Call this functions if you need to manually control the slides
$scope.next = function () {
  $ionicSlideBoxDelegate.next();
};

$scope.previous = function () {
  $ionicSlideBoxDelegate.previous();
};

$scope.goToSlide = function (index) {
  $scope.modal.show();
  $ionicSlideBoxDelegate.slide(index);
};

// Called each time the slide changes
$scope.slideChanged = function (index) {
  $scope.slideIndex = index;
};

// Functions run
if ($ionicHistory.currentStateName() === 'main.admin.emergencyDetail') {
  ctrl.getEmergency();
} else {
  ctrl.loadPictures('');
}
});

#2

As I rarely get replies in this forum to my questions, again here is the solution i found:

adding a timestamp to the ng-src forces the directive to force reload the image and so the new image in the cacheDirectory is shown.