Merge pull request #240 from paulplant/screen-lock

Improved Screen Lock function with optional Clock View
This commit is contained in:
Johan Degraeve 2021-06-01 23:27:56 +02:00 committed by GitHub
commit 4530449def
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 419 additions and 48 deletions

View File

@ -12,12 +12,30 @@ enum ConstantsUI {
/// color to use for disclosure indicator in settings views
static let disclosureIndicatorColor = UIColor.gray
/// define the formatting to be used to style the segmented controls on the home screen
/// segmentedControl font size
static let segmentedControlFont = UIFont.systemFont(ofSize: 11)
/// segmentedControl background color
static let segmentedControlBackgroundColor = UIColor.init(white: 0.05, alpha: 1)
/// segmentedControl border width
static let segmentedControlBorderWidth: CGFloat = 0.0
/// segmentedControl font color
static let segmentedControlNormalTextColor = UIColor.gray
/// segmentedControl font color when selected
static let segmentedControlSelectedTextColor = UIColor.black
/// segmentedControl background color when selected
static let segmentedControlSelectedTintColor = UIColor.lightGray
/// colors for lock screen button in toolbar
static let screenLockIconColor = UIColor.gray
/// value label font size when the screen is in normal operation mode
static let valueLabelFontSizeNormal = UIFont.systemFont(ofSize: 90)
/// value label font bigger size when the screen is in screen lock mode
static let valueLabelFontSizeScreenLock = UIFont.systemFont(ofSize: 120)
/// clock label font color. It shouldn't be too white or it could be distracting at night.
static let clockLabelColor = UIColor.lightGray
/// clock label font size (ideally should be set to the same as the bigger valueLabel font size
static let clockLabelFontSize = UIFont.systemFont(ofSize: 120)
}

View File

@ -21,7 +21,7 @@ extension UserDefaults {
// General
/// bloodglucose unit
/// bloodglucose unit
case bloodGlucoseUnitIsMgDl = "bloodGlucoseUnit"
/// urgent high value
case isMaster = "isMaster"
@ -31,6 +31,8 @@ extension UserDefaults {
case showReadingInAppBadge = "showReadingInAppBadge"
/// should reading by multiplied by 10
case multipleAppBadgeValueWith10 = "multipleAppBadgeValueWith10"
/// should the clock view be shown when the screen is locked?
case showClockWhenScreenIsLocked = "showClockWhenScreenIsLocked"
/// minimum time between two notifications, set by user
case notificationInterval = "notificationInterval"
@ -352,6 +354,17 @@ extension UserDefaults {
}
}
/// should the clock view be shown when the screen is locked?
@objc dynamic var showClockWhenScreenIsLocked: Bool {
// default value for bool in userdefaults is false, as default we want the clock to show when the screen is locked
get {
return !bool(forKey: Key.showClockWhenScreenIsLocked.rawValue)
}
set {
set(!newValue, forKey: Key.showClockWhenScreenIsLocked.rawValue)
}
}
// MARK: Home Screen Settings
/// the urgenthighmarkvalue in unit selected by user ie, mgdl or mmol

View File

@ -4,6 +4,7 @@
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@ -21,7 +22,7 @@
<rect key="frame" x="0.0" y="44" width="390" height="717"/>
<subviews>
<toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" barStyle="black" translucent="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tVG-ML-9xd">
<rect key="frame" x="0.0" y="0.0" width="390" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="390" height="54"/>
<items>
<barButtonItem title="Snooze" id="f3E-Tt-LBV">
<connections>
@ -39,22 +40,17 @@
<action selector="calibrateToolbarButtonAction:" destination="9pv-A4-QxB" id="qNA-1R-UK5"/>
</connections>
</barButtonItem>
<barButtonItem title="Lock" id="wfX-50-2w6">
<connections>
<action selector="screenLockToolbarButtonAction:" destination="9pv-A4-QxB" id="L14-hJ-4a9"/>
</connections>
</barButtonItem>
<barButtonItem style="plain" systemItem="flexibleSpace" id="Bnf-FN-LqX"/>
</items>
</toolbar>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="C16-NQ-F1Y">
<rect key="frame" x="0.0" y="44" width="390" height="541"/>
<rect key="frame" x="0.0" y="54" width="390" height="391"/>
<subviews>
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="---" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="We3-bN-ffR">
<rect key="frame" x="137" y="25.000000000000007" width="116" height="107.66666666666669"/>
<gestureRecognizers/>
<fontDescription key="fontDescription" type="system" pointSize="90"/>
<color key="textColor" systemColor="systemGreenColor"/>
<nil key="highlightedColor"/>
<connections>
<outletCollection property="gestureRecognizers" destination="tYH-fG-Lky" appends="YES" id="IyM-sF-P0i"/>
</connections>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" text="x mins ago" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uyn-2k-K74">
<rect key="frame" x="10" y="0.0" width="102" height="26.333333333333332"/>
<fontDescription key="fontDescription" type="system" pointSize="22"/>
@ -67,33 +63,56 @@
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="---" textAlignment="center" lineBreakMode="clip" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="We3-bN-ffR">
<rect key="frame" x="20" y="25.000000000000007" width="350" height="107.66666666666669"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<gestureRecognizers/>
<constraints>
<constraint firstAttribute="height" relation="lessThanOrEqual" constant="140" id="132-3f-vQI"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="90"/>
<color key="textColor" systemColor="systemGreenColor"/>
<nil key="highlightedColor"/>
<connections>
<outletCollection property="gestureRecognizers" destination="tYH-fG-Lky" appends="YES" id="8Ie-iQ-LNP"/>
</connections>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0nE-AX-r0w" customClass="BloodGlucoseChartView" customModule="xdrip" customModuleProvider="target">
<rect key="frame" x="10" y="132.66666666666666" width="380" height="408.33333333333337"/>
<rect key="frame" x="10" y="132.66666666666666" width="380" height="258.33333333333337"/>
<gestureRecognizers/>
<connections>
<outletCollection property="gestureRecognizers" destination="Fi5-iu-Usk" appends="YES" id="Rkv-hK-sLH"/>
<outletCollection property="gestureRecognizers" destination="axt-dD-sCA" appends="YES" id="Bxm-Qp-L3P"/>
</connections>
</view>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Wbt-Y0-6PL">
<rect key="frame" x="127" y="0.6666666666666643" width="24" height="24.333333333333336"/>
<imageReference key="image" image="lock.fill" catalog="system" symbolScale="default"/>
<preferredSymbolConfiguration key="preferredSymbolConfiguration" configurationType="pointSize" pointSize="22" scale="default"/>
</imageView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="7Wo-wd-80o" secondAttribute="trailing" constant="10" id="28x-56-97G"/>
<constraint firstAttribute="trailing" secondItem="0nE-AX-r0w" secondAttribute="trailing" id="4Kt-zl-bbl"/>
<constraint firstItem="Wbt-Y0-6PL" firstAttribute="leading" secondItem="uyn-2k-K74" secondAttribute="trailing" constant="15" id="8Us-MZ-OGv"/>
<constraint firstAttribute="bottom" secondItem="0nE-AX-r0w" secondAttribute="bottom" id="C61-10-Kdo"/>
<constraint firstItem="We3-bN-ffR" firstAttribute="leading" secondItem="C16-NQ-F1Y" secondAttribute="leading" constant="20" id="DjD-bz-O8N"/>
<constraint firstItem="Wbt-Y0-6PL" firstAttribute="centerY" secondItem="uyn-2k-K74" secondAttribute="centerY" id="ESH-24-icv"/>
<constraint firstAttribute="trailing" secondItem="We3-bN-ffR" secondAttribute="trailing" constant="20" id="LWb-Rj-dfs"/>
<constraint firstItem="uyn-2k-K74" firstAttribute="top" secondItem="C16-NQ-F1Y" secondAttribute="top" id="Luq-xy-Lzu"/>
<constraint firstItem="7Wo-wd-80o" firstAttribute="centerY" secondItem="uyn-2k-K74" secondAttribute="centerY" id="Qpl-lB-gwg"/>
<constraint firstItem="0nE-AX-r0w" firstAttribute="leading" secondItem="C16-NQ-F1Y" secondAttribute="leading" constant="10" id="e97-Zw-ipJ"/>
<constraint firstItem="0nE-AX-r0w" firstAttribute="top" secondItem="We3-bN-ffR" secondAttribute="bottom" id="emW-PI-WrN"/>
<constraint firstItem="uyn-2k-K74" firstAttribute="leading" secondItem="C16-NQ-F1Y" secondAttribute="leading" constant="10" id="mYE-7c-E2l"/>
<constraint firstItem="We3-bN-ffR" firstAttribute="centerX" secondItem="C16-NQ-F1Y" secondAttribute="centerX" id="vhA-TS-y2Z"/>
<constraint firstAttribute="bottom" secondItem="0nE-AX-r0w" secondAttribute="bottom" id="w6l-ym-Sl2"/>
<constraint firstItem="We3-bN-ffR" firstAttribute="top" secondItem="C16-NQ-F1Y" secondAttribute="top" constant="25" id="xak-Qv-s0j"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="x9u-yg-PXE" userLabel="segmentControlsView">
<rect key="frame" x="0.0" y="585" width="390" height="34"/>
<rect key="frame" x="0.0" y="445" width="390" height="34"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Nhe-d1-2e7">
<rect key="frame" x="10" y="4.6666666666666288" width="370" height="25"/>
<rect key="frame" x="10" y="4.6666666666666856" width="370" height="25"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qG7-Ub-mzA">
<rect key="frame" x="0.0" y="0.0" width="194" height="25"/>
@ -153,14 +172,14 @@
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="P8h-sd-0mD">
<rect key="frame" x="0.0" y="619" width="390" height="8"/>
<rect key="frame" x="0.0" y="479" width="390" height="8"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="8" id="j1I-lJ-Iyl"/>
</constraints>
</view>
<view userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MtJ-rx-OB9" userLabel="Statistics View">
<rect key="frame" x="0.0" y="627" width="390" height="90"/>
<rect key="frame" x="0.0" y="487" width="390" height="90"/>
<subviews>
<stackView opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="ZF3-Ii-L0R">
<rect key="frame" x="8" y="9" width="374" height="72"/>
@ -385,6 +404,25 @@
<constraint firstAttribute="trailingMargin" secondItem="ZF3-Ii-L0R" secondAttribute="trailing" id="x6Q-4Q-45y"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ETk-QH-u1x">
<rect key="frame" x="0.0" y="577" width="390" height="140"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="--:--" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="rSC-H3-vfk">
<rect key="frame" x="20" y="-1.6666666666666288" width="350" height="143.33333333333334"/>
<fontDescription key="fontDescription" type="system" pointSize="120"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="rSC-H3-vfk" firstAttribute="centerY" secondItem="ETk-QH-u1x" secondAttribute="centerY" id="851-Pv-rd6"/>
<constraint firstItem="rSC-H3-vfk" firstAttribute="leading" secondItem="ETk-QH-u1x" secondAttribute="leading" constant="20" id="MBM-cg-FkS"/>
<constraint firstAttribute="height" constant="140" id="QZb-1f-NFb"/>
<constraint firstItem="rSC-H3-vfk" firstAttribute="centerX" secondItem="ETk-QH-u1x" secondAttribute="centerX" id="fvi-mi-iHT"/>
<constraint firstAttribute="trailing" secondItem="rSC-H3-vfk" secondAttribute="trailing" constant="20" id="rYW-nQ-H74"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="x9u-yg-PXE" firstAttribute="top" secondItem="C16-NQ-F1Y" secondAttribute="bottom" id="WZ6-cn-zwk"/>
@ -411,6 +449,8 @@
<outlet property="chartLongPressGestureRecognizerOutlet" destination="axt-dD-sCA" id="mUZ-cu-720"/>
<outlet property="chartOutlet" destination="0nE-AX-r0w" id="ivs-se-S3b"/>
<outlet property="chartPanGestureRecognizerOutlet" destination="Fi5-iu-Usk" id="zn5-wp-DKt"/>
<outlet property="clockLabelOutlet" destination="rSC-H3-vfk" id="kqu-7I-7VN"/>
<outlet property="clockView" destination="ETk-QH-u1x" id="XuQ-dY-93L"/>
<outlet property="cvTitleLabelOutlet" destination="PZI-Ln-kfh" id="IKV-zy-dNM"/>
<outlet property="diffLabelOutlet" destination="7Wo-wd-80o" id="nnn-w9-1sX"/>
<outlet property="highLabelOutlet" destination="Xlz-6g-zzD" id="DyX-x0-PwZ"/>
@ -426,9 +466,12 @@
<outlet property="pieChartLabelOutlet" destination="c1z-wL-Eye" id="tBn-RJ-oiQ"/>
<outlet property="pieChartOutlet" destination="vm5-IB-4CY" id="t8a-2d-t5l"/>
<outlet property="preSnoozeToolbarButtonOutlet" destination="f3E-Tt-LBV" id="HyH-Pn-tQ6"/>
<outlet property="screenLockImageOutlet" destination="Wbt-Y0-6PL" id="TmY-3s-V27"/>
<outlet property="screenLockToolbarButtonOutlet" destination="wfX-50-2w6" id="r70-by-pce"/>
<outlet property="segmentedControlChartHours" destination="9LS-Vp-uGd" id="ymu-eS-Vpb"/>
<outlet property="segmentedControlStatisticsDays" destination="Xuy-hn-ozf" id="vOk-4p-M8g"/>
<outlet property="segmentedControlStatisticsDaysView" destination="qG7-Ub-mzA" id="shD-NU-LBm"/>
<outlet property="segmentedControlsView" destination="x9u-yg-PXE" id="U0O-Rt-EUR"/>
<outlet property="sensorToolbarButtonOutlet" destination="ZIM-Wf-bUy" id="kjL-rX-6ZV"/>
<outlet property="statisticsView" destination="MtJ-rx-OB9" id="u5w-qN-5Tq"/>
<outlet property="timePeriodLabelOutlet" destination="On3-dy-RgB" id="hAe-Kx-vnM"/>
@ -438,7 +481,7 @@
<placeholder placeholderIdentifier="IBFirstResponder" id="W5J-7L-Pyd" sceneMemberID="firstResponder"/>
<pongPressGestureRecognizer allowableMovement="10" minimumPressDuration="0.90000000000000002" id="tYH-fG-Lky">
<connections>
<action selector="valueLabelLongPressGestureRecognizerAction:" destination="9pv-A4-QxB" id="NlL-kQ-dpZ"/>
<action selector="valueLabelLongPressGestureRecognizerAction:" destination="9pv-A4-QxB" id="6V0-gW-Q4f"/>
</connections>
</pongPressGestureRecognizer>
<panGestureRecognizer minimumNumberOfTouches="1" id="Fi5-iu-Usk">
@ -1515,6 +1558,7 @@
<image name="Bluetooth" width="30" height="30"/>
<image name="Home" width="30" height="30"/>
<image name="Settings" width="30" height="30"/>
<image name="lock.fill" catalog="system" width="128" height="128"/>
<systemColor name="systemGrayColor">
<color red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>

View File

@ -99,3 +99,8 @@
/// for home view, license info
"licenseinfo" = "This program is free software distributed under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.\r\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.\r\n\nSee http://www.gnu.org/licenses/gpl.txt for more details.\r\n\r\nInfo: ";
"lock" = "Sperren";
"unlock" = "Entsperren";
"screenlocktitle" = "Bildschirmsperre aktiviert";
"screenlockinfo" = "Dadurch bleibt der Bildschirm aktiviert, bis zu einer anderen App gewechselt wird oder entsperren geklickt wird.\r\n\nWir empfehlen, dass Handy mit dem Ladekabel zu verbinden, um ein Entladen des Akkus zu verhindern.";

View File

@ -297,3 +297,5 @@
"settingsviews_daysToUseStatisticsMessage" = "Maximale Tage anhand dessen versucht wird den Verlauf zu berechnen?\n\n(Bei 0 wird heute ab Mitternacht berechnet)";
"settingsviews_useStandardStatisticsRange" = "Standardbereich verwenden?";
"settingsviews_useIFCCA1C" = "HbA1c in mmols/mol anzeigen?";
"showClockWhenScreenIsLocked" = "Uhr anzeigen wenn gesperrt?";

View File

@ -1,6 +1,10 @@
"presnooze" = "Snooze";
"sensor" = "Sensor";
"calibrate" = "Calibrate";
"lock" = "Lock";
"unlock" = "Unlock";
"screenlocktitle" = "Screen Lock Enabled";
"screenlockinfo" = "This will keep the screen awake until you move to another app or click Unlock.\r\n\nIt is recommended that you keep the phone plugged into a charger to prevent battery drain.";
"statusactiontitle" = "Status";
"scanbluetoothdeviceactiontitle" = "Scan for Transmitter";
"forgetbluetoothdeviceactiontitle" = "Forget Transmitter";

View File

@ -7,6 +7,7 @@
"showReadingInNotification" = "Show BG in Notifications?";
"labelShowReadingInAppBadge" = "Show BG in the App Badge?";
"multipleAppBadgeValueWith10" = "Multiply App Badge Reading by 10?";
"showClockWhenScreenIsLocked" = "Show Clock when Locked?";
"settingsviews_urgentHighValue" = "Urgent High Value:";
"settingsviews_highValue" = "High Value:";
"settingsviews_targetValue" = "Target Value:";

View File

@ -1,6 +1,10 @@
"presnooze" = "Snooze";
"transmitter" = "Transmisor";
"calibrate" = "Calibrar";
"lock" = "Bloquear";
"unlock" = "Desbloquear";
"screenlocktitle" = "Bloqueo de Pantalla Habilitado";
"screenlockinfo" = "Este mode mantendré la pantalla activada hasta que hagas click en 'Desbloquear' o que vuelves a la pantalla de inicio del iPhone.\r\n\nRecomendamos mantener el iPhone conectado a un cargador para evitar la descarga de la batería.";
"statusactiontitle" = "Estado";
"scanbluetoothdeviceactiontitle" = "Buscar Transmisor";
"forgetbluetoothdeviceactiontitle" = "Olvidar Transmisor";

View File

@ -7,6 +7,7 @@
"showReadingInNotification" = "Mostrar en Notificaciones?";
"labelShowReadingInAppBadge" = "Mostrar en el icono de la app?";
"multipleAppBadgeValueWith10" = "Multiplicar valor por 10 en el icono de la app?";
"showClockWhenScreenIsLocked" = "Mostrar reloj al bloquear?";
"settingsviews_urgentHighValue" = "Valor de Glucemia Alta (Urgente):";
"settingsviews_highValue" = "Valor de Glucemia Alta:";
"settingsviews_targetValue" = "Valor Objectivo:";

View File

@ -1,6 +1,10 @@
"presnooze" = "Snooze";
"sensor" = "Capteur";
"calibrate" = "Calibrer";
"lock" = "Verrouillé";
"unlock" = "Déverrouillé";
"screenlocktitle" = "Verrouillage d'écran activé";
"screenlockinfo" = "Cette option maintiendra votre écran éveillé jusqu'à ce que vous changiez d'application ou sélectionniez déverrouillé.\r\n\nIl est conseillé de laisser le téléphone sur son chargeur pour éviter que la batterie ne se décharge.";
"statusactiontitle" = "Statut";
"scanbluetoothdeviceactiontitle" = "Scanner le transmetteur";
"forgetbluetoothdeviceactiontitle" = "Oublier le transmetteur";

View File

@ -9,6 +9,7 @@
"showReadingInNotification" = "Afficher Glyc dans notification?";
"labelShowReadingInAppBadge" = "Afficher Glyc dans le badge?";
"multipleAppBadgeValueWith10" = "Multiplier par 10 dans le badge?";
"showClockWhenScreenIsLocked" = "Visualiser l'heure sur écran verrouillé?";
"settingsviews_sectiontitlestatistics" = "Statistiques";
"settingsviews_showStatistics" = "Visualiser les statistiques?";
"settingsviews_daysToUseStatisticsTitle" = "Nombre de jours?";

View File

@ -1,6 +1,10 @@
"presnooze" = "Sluimer";
"sensor" = "Sensor";
"calibrate" = "Kalibreer";
"lock" = "Lock";
"unlock" = "Unlock";
"screenlocktitle" = "Scherm Vergrendeld";
"screenlockinfo" = "Deze optie houdt de app op de voorgrond tot je een andere app opent, of tot je je toestel lockt.\r\n\nHet is aan te raden je toestel aan de oplader te houden om de batterij opgeladen te houden.";
"statusactiontitle" = "Status";
"scanbluetoothdeviceactiontitle" = "Scan voor Transmitter";
"forgetbluetoothdeviceactiontitle" = "Vergeet Transmitter";

View File

@ -11,6 +11,7 @@
"showReadingInNotification" = "Toon BG in Notificaties?";
"labelShowReadingInAppBadge" = "Toon BG in de App Badge?";
"multipleAppBadgeValueWith10" = "Vermenigvuldig App Badge Meting met 10?";
"showClockWhenScreenIsLocked" = "Toon klok indien gelockt?";
"settingsviews_urgentHighValue" = "Urgent Hoge Waarde:";
"settingsviews_highValue" = "Hoge Waarde:";
"settingsviews_targetValue" = "Doel Waarde:";

View File

@ -1,6 +1,10 @@
"presnooze" = "Snooza";
"sensor" = "Sensor";
"calibrate" = "Kalibrera";
"lock" = "Lås";
"unlock" = "Lås upp";
"screenlocktitle" = "Skärmlås på";
"screenlockinfo" = "Håller skärmen öppen tills du byter app eller klickar 'Lås upp'.\r\n\nDet rekommenderas att du har laddkabeln i för att förhindra urladdning av batteriet.";
"statusactiontitle" = "Status";
"scanbluetoothdeviceactiontitle" = "Scanna efter sändare";
"forgetbluetoothdeviceactiontitle" = "Glöm sändare";

View File

@ -7,6 +7,7 @@
"showReadingInNotification" = "Visa BS som notiser?";
"labelShowReadingInAppBadge" = "Visa BS i appikon?";
"multipleAppBadgeValueWith10" = "Multiplicera BS med 10?";
"showClockWhenScreenIsLocked" = "Visa klocka när skärmen är låst?";
"settingsviews_urgentHighValue" = "Akut högt värde:";
"settingsviews_highValue" = "Högt värde:";
"settingsviews_targetValue" = "Målvärde:";

View File

@ -16,6 +16,22 @@ enum Texts_HomeView {
return NSLocalizedString("calibrate", tableName: filename, bundle: Bundle.main, value: "Calibrate", comment: "Text in button on home screen")
}()
static let lockButton:String = {
return NSLocalizedString("lock", tableName: filename, bundle: Bundle.main, value: "Lock", comment: "Text in button on home screen")
}()
static let unlockButton:String = {
return NSLocalizedString("unlock", tableName: filename, bundle: Bundle.main, value: "Unlock", comment: "Text in button on home screen")
}()
static let screenLockTitle:String = {
return NSLocalizedString("screenlocktitle", tableName: filename, bundle: Bundle.main, value: "Screen Lock Enabled", comment: "Screen Lock Title")
}()
static let screenLockInfo:String = {
return NSLocalizedString("screenlockinfo", tableName: filename, bundle: Bundle.main, value: "This will keep the screen awake until you move to another app or click Unlock.\r\n\nIt is recommended that you keep the phone plugged into a charger to prevent battery drain.", comment: "Info message to explain screen lock function")
}()
static let statusActionTitle:String = {
return NSLocalizedString("statusactiontitle", tableName: filename, bundle: Bundle.main, value: "Status", comment: "when user clicks transmitterButton, this is the first action, to show the status")
}()

View File

@ -44,6 +44,10 @@ class Texts_SettingsView {
return NSLocalizedString("multipleAppBadgeValueWith10", tableName: filename, bundle: Bundle.main, value: "Multiply App Badge Reading by 10?", comment: "general settings, should reading be multiplied with 10 yes or no")
}()
static let showClockWhenScreenIsLocked: String = {
return NSLocalizedString("showClockWhenScreenIsLocked", tableName: filename, bundle: Bundle.main, value: "Show Clock when Locked?", comment: "general settings, should the clock also be displayed when the screen is locked?")
}()
static let warningChangeFromMasterToFollower: String = {
return NSLocalizedString("warningChangeFromMasterToFollower", tableName: filename, bundle: Bundle.main, value: "Switch from master to follower will stop your current sensor. Do you want to continue ?", comment: "general settings, when switching from master to follower, if confirmation is asked, this message will be shown.")
}()

View File

@ -16,7 +16,7 @@ final class RootViewController: UIViewController {
@IBOutlet weak var preSnoozeToolbarButtonOutlet: UIBarButtonItem!
@IBAction func preSnoozeToolbarButtonAction(_ sender: UIBarButtonItem) {
// // opens the SnoozeViewController, see storyboard
// opens the SnoozeViewController, see storyboard
}
@IBOutlet weak var sensorToolbarButtonOutlet: UIBarButtonItem!
@ -37,13 +37,21 @@ final class RootViewController: UIViewController {
} else {
trace("calibration : user clicks calibrate button", log: self.log, category: ConstantsLog.categoryRootView, type: .info)
trace("calibration : user clicked the calibrate button", log: self.log, category: ConstantsLog.categoryRootView, type: .info)
requestCalibration(userRequested: true)
}
}
/// outlet for the lock button - it will change text based upon whether they screen is locked or not
@IBOutlet weak var screenLockToolbarButtonOutlet: UIBarButtonItem!
/// call the screen lock alert when the button is pressed
@IBAction func screenLockToolbarButtonAction(_ sender: UIBarButtonItem) {
screenLockAlert(showClock: true)
}
/// outlet for label that shows how many minutes ago and so on
@IBOutlet weak var minutesLabelOutlet: UILabel!
@ -51,12 +59,24 @@ final class RootViewController: UIViewController {
/// outlet for label that shows difference with previous reading
@IBOutlet weak var diffLabelOutlet: UILabel!
/// outlet for the image of the screen lock symbol
@IBOutlet weak var screenLockImageOutlet: UIImageView!
/// outlet for label that shows the current reading
@IBOutlet weak var valueLabelOutlet: UILabel!
@IBAction func valueLabelLongPressGestureRecognizerAction(_ sender: UILongPressGestureRecognizer) {
valueLabelLongPressed(sender)
}
/// outlet for chart
@IBOutlet weak var chartOutlet: BloodGlucoseChartView!
@IBOutlet weak var segmentedControlsView: UIView!
/// outlets for chart time period selector
@IBOutlet weak var segmentedControlChartHours: UISegmentedControl!
@ -105,6 +125,7 @@ final class RootViewController: UIViewController {
}
/// an optional spacer view that we use to separate the segmented controls from the nav bar if the statistics are not shown
@IBOutlet weak var optionalSpacerView: UIView!
/// outlets for statistics view
@ -128,10 +149,11 @@ final class RootViewController: UIViewController {
@IBOutlet weak var timePeriodLabelOutlet: UILabel!
@IBOutlet weak var activityMonitorOutlet: UIActivityIndicatorView!
/// user long pressed the value label
@IBAction func valueLabelLongPressGestureRecognizerAction(_ sender: UILongPressGestureRecognizer) {
valueLabelLongPressed(sender)
}
/// clock view
@IBOutlet weak var clockView: UIView!
@IBOutlet weak var clockLabelOutlet: UILabel!
@IBAction func chartPanGestureRecognizerAction(_ sender: UIPanGestureRecognizer) {
@ -223,6 +245,9 @@ final class RootViewController: UIViewController {
/// constant for key in ApplicationManager.shared.addClosureToRunWhenAppWillEnterForeground - to initialize the glucoseChartManager and update labels and chart
private let applicationManagerKeyUpdateLabelsAndChart = "applicationManagerKeyUpdateLabelsAndChart"
/// constant for key in ApplicationManager.shared.addClosureToRunWhenAppWillEnterForeground - to dismiss screenLockAlertController
private let applicationManagerKeyDismissScreenLockAlertController = "applicationManagerKeyDismissScreenLockAlertController"
// MARK: - Properties - other private properties
/// for logging
@ -310,6 +335,18 @@ final class RootViewController: UIViewController {
/// when was the last notification created with bgreading, setting to 1 1 1970 initially to avoid having to unwrap it
private var timeStampLastBGNotification = Date(timeIntervalSince1970: 0)
/// to hold the current state of the screen keep-alive
private var screenIsLocked: Bool = false
/// date formatter for the clock view
private var clockDateFormatter = DateFormatter()
/// initiate a Timer object that we will use later to keep the clock view updated if the user activates the screen lock
private var clockTimer: Timer?
/// UIAlertController to use when user chooses to lock the screen. Defined here so we can dismiss it when app goes to the background
private var screenLockAlertController: UIAlertController?
// MARK: - overriden functions
// set the status bar content colour to light to match new darker theme
@ -324,19 +361,23 @@ final class RootViewController: UIViewController {
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// viewWillAppear when user switches eg from Settings Tab to Home Tab - latest reading value needs to be shown on the view, and also update minutes ago etc.
updateLabelsAndChart(overrideApplicationState: true)
// show the statistics view as required. If not, hide it and show the spacer view to keep segmentedControlChartHours separated a bit more away from the main Tab bar
statisticsView.isHidden = !UserDefaults.standard.showStatistics
if !screenIsLocked {
statisticsView.isHidden = !UserDefaults.standard.showStatistics
}
segmentedControlStatisticsDaysView.isHidden = !UserDefaults.standard.showStatistics
optionalSpacerView.isHidden = UserDefaults.standard.showStatistics
if screenIsLocked {
optionalSpacerView.isHidden = UserDefaults.standard.showClockWhenScreenIsLocked
}
if inRangeStatisticLabelOutlet.text == "-" {
activityMonitorOutlet.isHidden = true
@ -347,8 +388,6 @@ final class RootViewController: UIViewController {
// update statistics related outlets
updateStatistics(animatePieChart: true, overrideApplicationState: true)
}
override func viewDidAppear(_ animated: Bool) {
@ -361,6 +400,19 @@ final class RootViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// set up the clock view
clockDateFormatter.dateStyle = .none
clockDateFormatter.timeStyle = .short
clockDateFormatter.dateFormat = "HH:mm"
clockLabelOutlet.font = ConstantsUI.clockLabelFontSize
clockLabelOutlet.textColor = ConstantsUI.clockLabelColor
// ensure the screen lock icon color as per constants file and also the screen layout
screenLockImageOutlet.tintColor = ConstantsUI.screenLockIconColor
screenLockUpdate(enabled: false)
// this is to force update of userdefaults that are also stored in the shared user defaults
// these are used by the today widget. After a year or so (september 2021) this can all be deleted
UserDefaults.standard.urgentLowMarkValueInUserChosenUnit = UserDefaults.standard.urgentLowMarkValueInUserChosenUnit
@ -532,6 +584,9 @@ final class RootViewController: UIViewController {
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.multipleAppBadgeValueWith10.rawValue, options: .new, context: nil)
// also update of unit requires update of badge
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.bloodGlucoseUnitIsMgDl.rawValue, options: .new, context: nil)
// update show clock value for the screen lock function
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.showClockWhenScreenIsLocked.rawValue, options: .new, context: nil)
// high mark , low mark , urgent high mark, urgent low mark. change requires redraw of graph
UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.urgentLowMarkValue.rawValue, options: .new, context: nil)
@ -556,7 +611,7 @@ final class RootViewController: UIViewController {
}
}
// setup self as delegate for tabbarcontrolelr
// setup self as delegate for tabbarcontroller
self.tabBarController?.delegate = self
// setup the timer logic for updating the view regularly
@ -565,9 +620,13 @@ final class RootViewController: UIViewController {
// setup AVAudioSession
setupAVAudioSession()
// user may have long pressed the value label, so the screen will not lock, when going back to background, set isIdleTimerDisabled back to false
// user may have activated the screen lock function so that the screen stays open, when going back to background, set isIdleTimerDisabled back to false and update the UI so that it's ready to come to foreground when required.
ApplicationManager.shared.addClosureToRunWhenAppDidEnterBackground(key: applicationManagerKeyIsIdleTimerDisabled, closure: {
UIApplication.shared.isIdleTimerDisabled = false
self.screenLockUpdate(enabled: false)
})
// add tracing when app goes from foreground to background
@ -595,6 +654,13 @@ final class RootViewController: UIViewController {
})
ApplicationManager.shared.addClosureToRunWhenAppWillEnterForeground(key: applicationManagerKeyDismissScreenLockAlertController, closure: {
self.dismissScreenLockAlertController()
})
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
@ -1116,6 +1182,13 @@ final class RootViewController: UIViewController {
// refresh statistics calculations/view is necessary
updateStatistics(animatePieChart: true, overrideApplicationState: false)
case UserDefaults.Key.showClockWhenScreenIsLocked:
// refresh screenLock function if it is currently activated in order to show/hide the clock as requested
if screenIsLocked {
screenLockUpdate(enabled: true)
}
default:
break
@ -1153,6 +1226,7 @@ final class RootViewController: UIViewController {
preSnoozeToolbarButtonOutlet.title = Texts_HomeView.snoozeButton
sensorToolbarButtonOutlet.title = Texts_HomeView.sensor
calibrateToolbarButtonOutlet.title = Texts_HomeView.calibrationButton
screenLockToolbarButtonOutlet.title = screenIsLocked ? Texts_HomeView.unlockButton : Texts_HomeView.lockButton
chartLongPressGestureRecognizerOutlet.delegate = self
chartPanGestureRecognizerOutlet.delegate = self
@ -1815,17 +1889,16 @@ final class RootViewController: UIViewController {
}
}
private func valueLabelLongPressed(_ sender: UILongPressGestureRecognizer) {
if sender.state == .began {
if sender.state == .began && !screenIsLocked {
// vibrate so that user knows the long press is detected
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
// prevent screen lock
UIApplication.shared.isIdleTimerDisabled = true
// call the UIAlert but assume that the user wants a simple screen lock, not the full lock mode
screenLockAlert(overrideScreenIsLocked: true, showClock: false)
}
}
private func getCGMTransmitterDeviceName(for cgmTransmitter: CGMTransmitter) -> String? {
@ -2048,10 +2121,171 @@ final class RootViewController: UIViewController {
}
})
}
/// swaps status from locked to unlocked or vice versa, and creates alert to inform user
/// - parameters:
/// - overrideScreenIsLocked : if true, then screen will be locked even if it's already locked. If false, then status swaps from locked to unlocked or unlocked to locked
/// - showClock : when true this parameter will be passed to the screeLockUpdate function and this will lock the screen in the full lock mode adjusting font sizes and showing the clock as required.
private func screenLockAlert(overrideScreenIsLocked: Bool = false, showClock: Bool = true) {
if !screenIsLocked || overrideScreenIsLocked {
trace("screen lock : user clicked the lock button or long pressed the value", log: self.log, category: ConstantsLog.categoryRootView, type: .info)
// vibrate so that user knows the long press is detected
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
// lock and update the screen
self.screenLockUpdate(enabled: true, showClock: showClock)
// create uialertcontroller to inform user
screenLockAlertController = UIAlertController(title: Texts_HomeView.screenLockTitle, message: Texts_HomeView.screenLockInfo, preferredStyle: .alert)
// create buttons for uialertcontroller
let OKAction = UIAlertAction(title: Texts_Common.Ok, style: .default) {
(action:UIAlertAction!) in
// set screenLockAlertController to nil because this variable is used when app comes to foreground, to check if alert is still presented
self.screenLockAlertController = nil
}
// add buttons to the alert
screenLockAlertController!.addAction(OKAction)
// show alert
self.present(screenLockAlertController!, animated: true, completion:nil)
// schedule timer to dismiss the uialert controller after some time, in case user doesn't click ok
Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(dismissScreenLockAlertController), userInfo: nil, repeats:false)
} else {
trace("screen lock : user clicked the unlock button", log: self.log, category: ConstantsLog.categoryRootView, type: .info)
// this means the user has clicked the button whilst the screen look in already in place so let's turn the function off
self.screenLockUpdate(enabled: false, showClock: showClock)
}
}
/// this function will run when the user wants the screen to lock, or whenever the view appears and it will set up the screen correctly for each mode
/// - parameters :
/// - enabled : when true this will force the screen to lock
/// - showClock : when false, this will enable a simple screen lock without changing the UI - useful for keeping the screen open on your desk
private func screenLockUpdate(enabled: Bool = true, showClock: Bool = true) {
if enabled {
// set screen lock icon color to value defined in constants file
screenLockImageOutlet.isHidden = false
// set the toolbar button text to "Unlock"
screenLockToolbarButtonOutlet.title = Texts_HomeView.unlockButton
if showClock {
// set the value label font size to big
valueLabelOutlet.font = ConstantsUI.valueLabelFontSizeScreenLock
// de-clutter the screen. Hide the statistics view, controls and show the clock view
statisticsView.isHidden = true
segmentedControlsView.isHidden = true
if UserDefaults.standard.showClockWhenScreenIsLocked {
// set the clock label font size to big (force ConstantsUI implementation)
clockLabelOutlet.font = ConstantsUI.clockLabelFontSize
// set clock label color
clockLabelOutlet.textColor = ConstantsUI.clockLabelColor
optionalSpacerView.isHidden = true
clockView.isHidden = false
// set the format for the clock view and update it to show the current time
updateClockView()
// set a timer instance to update the clock view label every second
clockTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateClockView), userInfo: nil, repeats:true)
} else {
optionalSpacerView.isHidden = false
clockView.isHidden = true
}
}
// prevent screen dim/lock
UIApplication.shared.isIdleTimerDisabled = true
// set the private var so that we can track the screen lock activation within the RootViewController
screenIsLocked = true
trace("screen lock : screen lock / keep-awake enabled", log: self.log, category: ConstantsLog.categoryRootView, type: .info)
} else {
// hide the lock image
screenLockImageOutlet.isHidden = true
// set the toolbar button text to "Lock"
screenLockToolbarButtonOutlet.title = Texts_HomeView.lockButton
valueLabelOutlet.font = ConstantsUI.valueLabelFontSizeNormal
// hide
statisticsView.isHidden = !UserDefaults.standard.showStatistics
segmentedControlsView.isHidden = false
optionalSpacerView.isHidden = UserDefaults.standard.showStatistics
clockView.isHidden = true
if showClock {
// destroy the timer instance so that it doesn't keep using resources
clockTimer?.invalidate()
}
// make sure that the screen lock is deactivated
UIApplication.shared.isIdleTimerDisabled = false
trace("screen lock / keep-awake disabled", log: self.log, category: ConstantsLog.categoryRootView, type: .info)
screenIsLocked = false
}
}
/// update the label in the clock view every time this function is called
@objc private func updateClockView() {
self.clockLabelOutlet.text = clockDateFormatter.string(from: Date())
}
/// checks if screenLockAlertController is not nil and if not dismisses the presentedViewController
@objc private func dismissScreenLockAlertController() {
// possibly screenLockAlertController is still on the screen which would happen if user chooses to lock the screen but brings the app to the background before clicking ok
if self.screenLockAlertController != nil {
self.presentedViewController?.dismiss(animated: false, completion: nil)
self.screenLockAlertController = nil
}
}
}

View File

@ -8,18 +8,21 @@ fileprivate enum Setting:Int, CaseIterable {
/// choose between master and follower
case masterFollower = 1
/// if reading is shown in app badge, should value be multiplied with 10 yes or no
case showClockWhenScreenIsLocked = 2
/// should reading be shown in notification
case showReadingInNotification = 2
case showReadingInNotification = 3
/// - minimum time between two readings, for which notification should be created (in minutes)
/// - except if there's been a disconnect, in that case this value is not taken into account
case notificationInterval = 3
case notificationInterval = 4
/// show reading in app badge
case showReadingInAppBadge = 4
case showReadingInAppBadge = 5
/// if reading is shown in app badge, should value be multiplied with 10 yes or no
case multipleAppBadgeValueWith10 = 5
case multipleAppBadgeValueWith10 = 6
}
@ -112,7 +115,7 @@ class SettingsViewGeneralSettingsViewModel: SettingsViewModelProtocol {
}
case .showReadingInNotification, .showReadingInAppBadge, .multipleAppBadgeValueWith10:
case .showReadingInNotification, .showReadingInAppBadge, .multipleAppBadgeValueWith10, .showClockWhenScreenIsLocked:
return SettingsSelectedRowAction.nothing
case .notificationInterval:
@ -158,6 +161,9 @@ class SettingsViewGeneralSettingsViewModel: SettingsViewModelProtocol {
case .multipleAppBadgeValueWith10:
return Texts_SettingsView.multipleAppBadgeValueWith10
case .showClockWhenScreenIsLocked:
return Texts_SettingsView.showClockWhenScreenIsLocked
case .notificationInterval:
return Texts_SettingsView.settingsviews_IntervalTitle
@ -175,7 +181,7 @@ class SettingsViewGeneralSettingsViewModel: SettingsViewModelProtocol {
case .masterFollower:
return UITableViewCell.AccessoryType.none
case .showReadingInNotification, .showReadingInAppBadge, .multipleAppBadgeValueWith10:
case .showReadingInNotification, .showReadingInAppBadge, .multipleAppBadgeValueWith10, .showClockWhenScreenIsLocked:
return UITableViewCell.AccessoryType.none
case .notificationInterval:
@ -195,7 +201,7 @@ class SettingsViewGeneralSettingsViewModel: SettingsViewModelProtocol {
case .masterFollower:
return UserDefaults.standard.isMaster ? Texts_SettingsView.master:Texts_SettingsView.follower
case .showReadingInNotification, .showReadingInAppBadge, .multipleAppBadgeValueWith10:
case .showReadingInNotification, .showReadingInAppBadge, .multipleAppBadgeValueWith10, .showClockWhenScreenIsLocked:
return nil
case .notificationInterval:
@ -220,6 +226,10 @@ class SettingsViewGeneralSettingsViewModel: SettingsViewModelProtocol {
case .multipleAppBadgeValueWith10:
return UISwitch(isOn: UserDefaults.standard.multipleAppBadgeValueWith10, action: {(isOn:Bool) in UserDefaults.standard.multipleAppBadgeValueWith10 = isOn})
case .showClockWhenScreenIsLocked:
return UISwitch(isOn: UserDefaults.standard.showClockWhenScreenIsLocked, action: {(isOn:Bool) in UserDefaults.standard.showClockWhenScreenIsLocked = isOn})
case .bloodGlucoseUnit, .masterFollower:
return nil