battery.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * This file is part of Threema Web.
  3. *
  4. * Threema Web is free software: you can redistribute it and/or modify it
  5. * under the terms of the GNU Affero General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or (at
  7. * your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Affero General Public License
  15. * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. import {Logger} from 'ts-log';
  18. import {LogService} from './log';
  19. import {NotificationService} from './notification';
  20. export class BatteryStatusService {
  21. // Attributes
  22. private batteryStatus: threema.BatteryStatus = null;
  23. private alertedLow = false;
  24. private alertedCritical = false;
  25. // Constants
  26. private static readonly PERCENT_LOW = 20;
  27. private static readonly PERCENT_CRITICAL = 5;
  28. // Services
  29. private $translate: ng.translate.ITranslateService;
  30. private notificationService: NotificationService;
  31. // Logging
  32. private readonly log: Logger;
  33. public static $inject = ['$translate', 'LogService', 'NotificationService'];
  34. constructor($translate: ng.translate.ITranslateService,
  35. logService: LogService, notificationService: NotificationService) {
  36. this.$translate = $translate;
  37. this.notificationService = notificationService;
  38. this.log = logService.getLogger('BatteryStatus-S');
  39. }
  40. /**
  41. * Update the battery status.
  42. */
  43. public setStatus(batteryStatus: threema.BatteryStatus): void {
  44. this.log.debug('Status:', batteryStatus);
  45. // Handle null percent value. This can happen if the battery status could not be determined.
  46. if (batteryStatus.percent === null) {
  47. this.clearStatus();
  48. return;
  49. }
  50. this.batteryStatus = batteryStatus;
  51. // Alert if percent drops below a certain threshold
  52. if (!batteryStatus.isCharging) {
  53. if (!this.alertedCritical && batteryStatus.percent < BatteryStatusService.PERCENT_CRITICAL) {
  54. this.notifyLevel('critical');
  55. this.alertedCritical = true;
  56. } else if (!this.alertedLow && batteryStatus.percent < BatteryStatusService.PERCENT_LOW) {
  57. this.notifyLevel('low');
  58. this.alertedLow = true;
  59. }
  60. }
  61. // Reset alert flag if device is plugged in
  62. if (this.alertedLow && batteryStatus.isCharging) {
  63. this.alertedLow = false;
  64. this.notificationService.hideNotification('battery-low');
  65. }
  66. if (this.alertedCritical && batteryStatus.isCharging) {
  67. this.alertedCritical = false;
  68. this.notificationService.hideNotification('battery-critical');
  69. }
  70. // Reset alert flag if percentage goes above a certain threshold
  71. const hysteresis = 3;
  72. if (this.alertedLow && batteryStatus.percent > BatteryStatusService.PERCENT_LOW + hysteresis) {
  73. this.alertedLow = false;
  74. this.notificationService.hideNotification('battery-low');
  75. }
  76. if (this.alertedCritical && batteryStatus.percent > BatteryStatusService.PERCENT_CRITICAL + hysteresis) {
  77. this.alertedCritical = false;
  78. this.notificationService.hideNotification('battery-critical');
  79. }
  80. }
  81. /**
  82. * Clear the battery status information.
  83. */
  84. public clearStatus(): void {
  85. this.batteryStatus = null;
  86. }
  87. /**
  88. * Is battery status information available?
  89. */
  90. public get dataAvailable(): boolean {
  91. return this.batteryStatus !== null;
  92. }
  93. /**
  94. * Return the charge level in percent.
  95. */
  96. public get percent(): number {
  97. return this.batteryStatus.percent;
  98. }
  99. /**
  100. * Return whether the battery is currently charging.
  101. */
  102. public get isCharging(): boolean {
  103. return this.batteryStatus.isCharging;
  104. }
  105. /**
  106. * Return whether the battery level is low (<20%).
  107. */
  108. public get isLow(): boolean {
  109. return this.batteryStatus.percent < BatteryStatusService.PERCENT_LOW;
  110. }
  111. /**
  112. * Return whether the battery level is critical (<20%).
  113. */
  114. public get isCritical(): boolean {
  115. return this.batteryStatus.percent < BatteryStatusService.PERCENT_CRITICAL;
  116. }
  117. /**
  118. * Alert the user about a certain battery level.
  119. */
  120. private notifyLevel(level: 'low' | 'critical'): void {
  121. if (!this.notificationService.getWantsNotifications()) {
  122. // User does not want notifications.
  123. // This flag is also checked in the `showNotification` function, but
  124. // we'll return early to avoid having to do the translations and to
  125. // keep the notification sound from playing without a visible
  126. // notification.
  127. return;
  128. }
  129. const title = this.$translate.instant('common.WARNING');
  130. const picture = 'img/ic_battery_alert-64x64.png';
  131. let tag: string;
  132. let body: string;
  133. if (level === 'low') {
  134. tag = 'battery-low';
  135. body = this.$translate.instant('battery.LEVEL_LOW', { percent: this.percent });
  136. this.notificationService.hideNotification('battery-critical');
  137. } else if (level === 'critical') {
  138. tag = 'battery-critical';
  139. body = this.$translate.instant('battery.LEVEL_CRITICAL', { percent: this.percent });
  140. this.notificationService.hideNotification('battery-low');
  141. }
  142. this.notificationService.showNotification(tag, title, body, picture, undefined, true, true);
  143. }
  144. public toString(): string {
  145. if (this.batteryStatus === null) {
  146. return 'No data';
  147. }
  148. return this.percent + '%, ' + (this.isCharging ? 'charging' : 'discharging');
  149. }
  150. }