From 06ab1d1062b07569dc128f6fa6e2559fcff497de Mon Sep 17 00:00:00 2001 From: Sebastiaan Pasma Date: Mon, 25 Jun 2018 11:07:13 +0200 Subject: [PATCH] - remove native audio plugin references - soundService for playing sounds - file naming changed on sound files - Bug where sounds were playing when mute switch on iPhone was on - added cordova media plugin (with support for a fix the found mute-switch bug) - play all sounds to use the new soundService --- app-template/config-template.xml | 4 +- src/js/controllers/confirm.js | 7 +--- src/js/controllers/tab-receive.js | 30 +------------- src/js/services/soundService.js | 39 ++++++++++++++++++ ...coin_received.mp3 => payment_received.mp3} | Bin ...coin_received.ogg => payment_received.ogg} | Bin www/misc/{bch_sent.mp3 => payment_sent.mp3} | Bin www/misc/payment_sent.ogg | Bin 0 -> 14156 bytes 8 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 src/js/services/soundService.js rename www/misc/{coin_received.mp3 => payment_received.mp3} (100%) rename www/misc/{coin_received.ogg => payment_received.ogg} (100%) rename www/misc/{bch_sent.mp3 => payment_sent.mp3} (100%) create mode 100644 www/misc/payment_sent.ogg diff --git a/app-template/config-template.xml b/app-template/config-template.xml index ed4b192ba..239f78d6c 100644 --- a/app-template/config-template.xml +++ b/app-template/config-template.xml @@ -72,7 +72,9 @@ - + + + diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index fc92a2287..51c193d4a 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService) { +angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService, soundService) { var countDown = null; var FEE_TOO_HIGH_LIMIT_PER = 15; @@ -624,10 +624,7 @@ angular.module('copayApp.controllers').controller('confirmController', function( (processName == 'sendingTx' && !$scope.wallet.canSign() && !$scope.wallet.isPrivKeyExternal()) ) && !isOn) { $scope.sendStatus = 'success'; - if (config.soundsEnabled && $scope.wallet.coin == 'bch') { - var audio = new Audio('misc/bch_sent.mp3'); - audio.play(); - } + soundService.play('misc/payment_sent.mp3'); firebaseEventsService.logEvent('sent_bitcoin', { coin: $scope.wallet.coin }); $timeout(function() { $scope.$digest(); diff --git a/src/js/controllers/tab-receive.js b/src/js/controllers/tab-receive.js index 32cd5281a..44db9b0bc 100644 --- a/src/js/controllers/tab-receive.js +++ b/src/js/controllers/tab-receive.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, txFormatService) { +angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, txFormatService, soundService) { var listeners = []; $scope.bchAddressType = { type: 'cashaddr' }; @@ -15,22 +15,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi var config; - var soundLoaded = false; - var nativeAudioAvailable = (window.plugins && window.plugins.NativeAudio); - - if (nativeAudioAvailable) { - window.plugins.NativeAudio.preloadSimple('received', 'misc/coin_received.mp3', function (msg) { - $log.debug('Receive sound loaded.'); - soundLoaded = true; - }, function (error) { - $log.debug('Error loading receive sound.'); - $log.debug(error); - }); - } else { - $log.debug('isNW: Using HTML5-Audio instead of native audio'); - soundLoaded = true; - } - $scope.displayBalanceAsFiat = true; $scope.requestSpecificAmount = function() { @@ -147,17 +131,7 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi } $scope.paymentReceivedCoin = $scope.wallet.coin; $scope.$apply(function () { - - if (config.soundsEnabled && soundLoaded) { - $log.debug('Play sound.'); - if (nativeAudioAvailable) { - window.plugins.NativeAudio.play('received'); - } else { - new Audio('misc/coin_received.ogg').play(); // NW.js has no mp3 support - } - } else { - $log.debug('Sound is disabled.'); - } + soundService.play('misc/payment_received.mp3'); $scope.showingPaymentReceived = true; }); } diff --git a/src/js/services/soundService.js b/src/js/services/soundService.js new file mode 100644 index 000000000..20318883f --- /dev/null +++ b/src/js/services/soundService.js @@ -0,0 +1,39 @@ +'use strict'; + +angular.module('copayApp.services').service('soundService', function($log, $timeout, platformInfo, configService) { + + var root = {}; + + /** + * Play a sound (when enabled in the configuration) using the Cordova Media-plugin (on Mobile) or html5-audio (on Desktop) relative to the www-root + * Make sure there is a .ogg file as well for NW.js (desktop) implementation + * @param soundFile + */ + root.play = function(soundFile) { + configService.whenAvailable(function(config) { + if (config.soundsEnabled) { + if (platformInfo.isCordova) { + var p = window.location.pathname; + var device_path = p.substring(0, p.lastIndexOf('/')); + var audio = new Media(device_path + '/' + soundFile, + function () { + $log.debug("playAudio(bch_sent):Audio Success"); + }, + function (err) { + $log.debug("playAudio():Audio Error: " + err); + } + ); + audio.play({playAudioWhenScreenIsLocked: false}); // XX SP: "Locked" is also the mute switch in iOS + } else { + if (platformInfo.isNW) { + soundFile = soundFile.substring(0, soundFile.lastIndexOf('.')) + ".ogg"; + $log.debug("Playing .ogg file ("+soundFile+"), as NW.js has no mp3 support"); + } + new Audio(soundFile).play(); + } + } + }); + }; + + return root; +}); \ No newline at end of file diff --git a/www/misc/coin_received.mp3 b/www/misc/payment_received.mp3 similarity index 100% rename from www/misc/coin_received.mp3 rename to www/misc/payment_received.mp3 diff --git a/www/misc/coin_received.ogg b/www/misc/payment_received.ogg similarity index 100% rename from www/misc/coin_received.ogg rename to www/misc/payment_received.ogg diff --git a/www/misc/bch_sent.mp3 b/www/misc/payment_sent.mp3 similarity index 100% rename from www/misc/bch_sent.mp3 rename to www/misc/payment_sent.mp3 diff --git a/www/misc/payment_sent.ogg b/www/misc/payment_sent.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8527a893cca30b57276062eb9e6ca6fb25898420 GIT binary patch literal 14156 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