mirror of
				https://github.com/house-of-abbey/GarminHomeAssistant.git
				synced 2025-10-29 23:08:14 +00:00 
			
		
		
		
	timers as statics, defensive popviews, no double confirmation, add pin
screen onBack, toggle state tweaks
This commit is contained in:
		| @@ -35,31 +35,43 @@ class HomeAssistantConfirmation extends WatchUi.Confirmation { | ||||
| //! Delegate to respond to the confirmation request. | ||||
| // | ||||
| class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate { | ||||
|     private var mConfirmMethod as Method(state as Lang.Boolean) as Void; | ||||
|     private var mTimer         as Timer.Timer or Null; | ||||
|     private var mState         as Lang.Boolean; | ||||
|     private var mToggleMethod  as Method(state as Lang.Boolean) as Void or Null; | ||||
|     private static var mTimer       as Timer.Timer or Null; | ||||
|  | ||||
|     private var mConfirmMethod      as Method(state as Lang.Boolean) as Void; | ||||
|     private var mState              as Lang.Boolean; | ||||
|     private var mToggleMethod       as Method(state as Lang.Boolean) as Void or Null; | ||||
|     private var mConfirmationView   as WatchUi.Confirmation; | ||||
|  | ||||
|     //! Class Constructor | ||||
|     //! | ||||
|     //! @param options A dictionary describing the following options: | ||||
|     //!  - callback Method to call on confirmation. | ||||
|     //!  - state    Wanted state of a toggle button. | ||||
|     //!  - toggle   Optional setEnabled method to untoggle ToggleItem. | ||||
|     //!  - callback         Method to call on confirmation. | ||||
|     //!  - confirmationView Confirmation the delegate is active for | ||||
|     //!  - state            Wanted state of a toggle button. | ||||
|     //!  - toggle           Optional setEnabled method to untoggle ToggleItem. | ||||
|     // | ||||
|     function initialize(options as { | ||||
|         :callback as Method(state as Lang.Boolean) as Void, | ||||
|         :confirmationView as WatchUi.Confirmation, | ||||
|         :state as Lang.Boolean, | ||||
|         :toggleMethod as Method(state as Lang.Boolean) or Null, | ||||
|     }) { | ||||
|         if (mTimer != null) { | ||||
|             mTimer.stop(); | ||||
|         } | ||||
|  | ||||
|         WatchUi.ConfirmationDelegate.initialize(); | ||||
|         mConfirmMethod = options[:callback]; | ||||
|         mConfirmationView = options[:confirmationView]; | ||||
|         mState         = options[:state]; | ||||
|         mToggleMethod  = options[:toggleMethod]; | ||||
|  | ||||
|         var timeout = Settings.getConfirmTimeout(); // ms | ||||
|         if (timeout > 0) { | ||||
|             mTimer = new Timer.Timer(); | ||||
|             if (mTimer == null) { | ||||
|                 mTimer = new Timer.Timer(); | ||||
|             } | ||||
|              | ||||
|             mTimer.start(method(:onTimeout), timeout, true); | ||||
|         } | ||||
|     } | ||||
| @@ -92,6 +104,10 @@ class HomeAssistantConfirmationDelegate extends WatchUi.ConfirmationDelegate { | ||||
|         if (mToggleMethod != null) { | ||||
|             mToggleMethod.invoke(!mState); | ||||
|         } | ||||
|         WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||
|  | ||||
|         var getCurrentView = WatchUi.getCurrentView(); | ||||
|         if (getCurrentView[0] == mConfirmationView) { | ||||
|             WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -244,6 +244,11 @@ class HomeAssistantPinConfirmationDelegate extends WatchUi.BehaviorDelegate { | ||||
|                         mTimer.stop(); | ||||
|                     } | ||||
|                     WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||
|  | ||||
|                     // Set the toggle, if we have one | ||||
|                     if (mToggleMethod != null) { | ||||
|                         mToggleMethod.invoke(!mState); | ||||
|                     } | ||||
|                     mConfirmMethod.invoke(mState); | ||||
|                 } else { | ||||
|                     error(); | ||||
| @@ -285,10 +290,7 @@ class HomeAssistantPinConfirmationDelegate extends WatchUi.BehaviorDelegate { | ||||
|         if (mTimer != null) { | ||||
|             mTimer.stop(); | ||||
|         } | ||||
|         // Undo the toggle, if we have one | ||||
|         if (mToggleMethod != null) { | ||||
|             mToggleMethod.invoke(!mState); | ||||
|         } | ||||
|          | ||||
|         WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||
|     } | ||||
|  | ||||
| @@ -314,6 +316,13 @@ class HomeAssistantPinConfirmationDelegate extends WatchUi.BehaviorDelegate { | ||||
|         goBack(); | ||||
|     } | ||||
|  | ||||
|     //! Handle the back button (ESC) | ||||
|     // | ||||
|     function onBack() as Lang.Boolean { | ||||
|         goBack(); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -140,7 +140,7 @@ class HomeAssistantService { | ||||
|                     :service => service, | ||||
|                     :data => data, | ||||
|                     :exit => exit, | ||||
|                 }), | ||||
|                 }, dialog), | ||||
|                 WatchUi.SLIDE_LEFT | ||||
|             ); | ||||
|         } else if (! phoneConnected) { | ||||
|   | ||||
| @@ -92,14 +92,33 @@ class HomeAssistantTapMenuItem extends HomeAssistantMenuItem { | ||||
|                 ); | ||||
|             } | ||||
|         } else if (mConfirm) { | ||||
|             WatchUi.pushView( | ||||
|                 new HomeAssistantConfirmation(), | ||||
|                 new HomeAssistantConfirmationDelegate({ | ||||
|                     :callback       => method(:onConfirm), | ||||
|                     :state          => false, | ||||
|                 }), | ||||
|                 WatchUi.SLIDE_IMMEDIATE | ||||
|             ); | ||||
|             var phoneConnected = System.getDeviceSettings().phoneConnected; | ||||
|             var internetAvailable = System.getDeviceSettings().connectionAvailable; | ||||
|             if ((! phoneConnected || ! internetAvailable) && Settings.getWifiLteExecutionEnabled()) { | ||||
|                 var dialogMsg = WatchUi.loadResource($.Rez.Strings.WifiLtePrompt) as Lang.String; | ||||
|                 var dialog = new WatchUi.Confirmation(dialogMsg); | ||||
|                 WatchUi.pushView( | ||||
|                     dialog, | ||||
|                     new WifiLteExecutionConfirmDelegate({ | ||||
|                         :type => "service", | ||||
|                         :service => mService, | ||||
|                         :data => mData, | ||||
|                         :exit => mExit, | ||||
|                     }, dialog), | ||||
|                     WatchUi.SLIDE_LEFT | ||||
|                 ); | ||||
|             } else { | ||||
|                 var view = new HomeAssistantConfirmation(); | ||||
|                 WatchUi.pushView( | ||||
|                     view, | ||||
|                     new HomeAssistantConfirmationDelegate({ | ||||
|                         :callback       => method(:onConfirm), | ||||
|                         :confirmationView => view, | ||||
|                         :state          => false, | ||||
|                     }), | ||||
|                     WatchUi.SLIDE_IMMEDIATE | ||||
|                 ); | ||||
|             } | ||||
|         } else { | ||||
|             onConfirm(false); | ||||
|         } | ||||
|   | ||||
| @@ -240,10 +240,6 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { | ||||
|     //! @param s Boolean indicating the desired state of the toggle switch. | ||||
|     // | ||||
|     function setState(s as Lang.Boolean) as Void { | ||||
|         // Toggle the UI back, we'll wait for confirmation from the Home Assistant | ||||
|         // Note: with Zigbee2MQTT a.o. we may not always get the state in the response. | ||||
|         setEnabled(!isEnabled()); | ||||
|  | ||||
|         var phoneConnected = System.getDeviceSettings().phoneConnected; | ||||
|         var internetAvailable = System.getDeviceSettings().connectionAvailable; | ||||
|          | ||||
| @@ -256,28 +252,10 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { | ||||
|             ErrorView.show(WatchUi.loadResource($.Rez.Strings.NoInternet) as Lang.String); | ||||
|         } else { | ||||
|             var id  = mData.get("entity_id") as Lang.String; | ||||
|             var url = Settings.getApiUrl() + "/services/"; | ||||
|             if (s) { | ||||
|                 url = url + id.substring(0, id.find(".")) + "/turn_on"; | ||||
|             } else { | ||||
|                 url = url + id.substring(0, id.find(".")) + "/turn_off"; | ||||
|             } | ||||
|             var url = getUrl(id, s); | ||||
|  | ||||
|             if ((! phoneConnected || ! internetAvailable) && Settings.getWifiLteExecutionEnabled()) { | ||||
|                 var dialogMsg = WatchUi.loadResource($.Rez.Strings.WifiLtePrompt) as Lang.String; | ||||
|                 var dialog = new WatchUi.Confirmation(dialogMsg); | ||||
|                 WatchUi.pushView( | ||||
|                     dialog, | ||||
|                     new WifiLteExecutionConfirmDelegate({ | ||||
|                         :type => "entity", | ||||
|                         :url => url, | ||||
|                         :id => id, | ||||
|                         :data => mData, | ||||
|                         :callback => method(:setToggleStateWithData), | ||||
|                         :exit => mExit, | ||||
|                     }), | ||||
|                     WatchUi.SLIDE_LEFT | ||||
|                 ); | ||||
|                 wifiPrompt(s); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -311,6 +289,9 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { | ||||
|     function callService(b as Lang.Boolean) as Void { | ||||
|         var hasTouchScreen = System.getDeviceSettings().isTouchScreen; | ||||
|         if (mPin && hasTouchScreen) { | ||||
|             // Undo the toggle | ||||
|             setEnabled(!isEnabled()); | ||||
|  | ||||
|             var pin = Settings.getPin(); | ||||
|             if (pin != null) { | ||||
|                 var pinConfirmationView = new HomeAssistantPinConfirmationView(); | ||||
| @@ -327,15 +308,26 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { | ||||
|                 ); | ||||
|             } | ||||
|         } else if (mConfirm) { | ||||
|             WatchUi.pushView( | ||||
|                 new HomeAssistantConfirmation(), | ||||
|                 new HomeAssistantConfirmationDelegate({ | ||||
|                     :callback       => method(:onConfirm), | ||||
|                     :state          => b, | ||||
|                     :toggleMethod   => method(:setEnabled), | ||||
|                 }), | ||||
|                 WatchUi.SLIDE_IMMEDIATE | ||||
|             ); | ||||
|             // Undo the toggle | ||||
|             setEnabled(!isEnabled()); | ||||
|  | ||||
|             var phoneConnected = System.getDeviceSettings().phoneConnected; | ||||
|             var internetAvailable = System.getDeviceSettings().connectionAvailable; | ||||
|             if ((! phoneConnected || ! internetAvailable) && Settings.getWifiLteExecutionEnabled()) { | ||||
|                 wifiPrompt(b); | ||||
|             } else { | ||||
|                 var confirmationView = new HomeAssistantConfirmation(); | ||||
|                 WatchUi.pushView( | ||||
|                     confirmationView, | ||||
|                     new HomeAssistantConfirmationDelegate({ | ||||
|                         :callback           => method(:onConfirm), | ||||
|                         :confirmationView   => confirmationView, | ||||
|                         :state              => b, | ||||
|                         :toggleMethod       => method(:setEnabled), | ||||
|                     }), | ||||
|                     WatchUi.SLIDE_IMMEDIATE | ||||
|                 ); | ||||
|             } | ||||
|         } else { | ||||
|             onConfirm(b); | ||||
|         } | ||||
| @@ -349,4 +341,45 @@ class HomeAssistantToggleMenuItem extends WatchUi.ToggleMenuItem { | ||||
|         setState(b); | ||||
|     } | ||||
|  | ||||
|     //! Displays a confirmation dialog before executing a service call via Wi-Fi/LTE. | ||||
|     //! | ||||
|     //! @param s Desired state: `true` to turn on, `false` to turn off. | ||||
|     // | ||||
|     private function wifiPrompt(s as Lang.Boolean) as Void { | ||||
|         var id  = mData.get("entity_id") as Lang.String; | ||||
|         var url = getUrl(id, s); | ||||
|  | ||||
|         var dialogMsg = WatchUi.loadResource($.Rez.Strings.WifiLtePrompt) as Lang.String; | ||||
|         var dialog = new WatchUi.Confirmation(dialogMsg); | ||||
|         WatchUi.pushView( | ||||
|             dialog, | ||||
|             new WifiLteExecutionConfirmDelegate({ | ||||
|                 :type => "entity", | ||||
|                 :url => url, | ||||
|                 :id => id, | ||||
|                 :data => mData, | ||||
|                 :callback => method(:setToggleStateWithData), | ||||
|                 :exit => mExit, | ||||
|             }, dialog), | ||||
|             WatchUi.SLIDE_LEFT | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     //! Constructs a Home Assistant API URL for the given entity and desired state. | ||||
|     //! | ||||
|     //! @param id The entity ID, e.g., `"switch.kitchen"`. | ||||
|     //! @param s Desired state: `true` for "turn_on", `false` for "turn_off". | ||||
|     //! | ||||
|     //! @return Full service URL string. | ||||
|     // | ||||
|     private function getUrl(id as Lang.String, s as Lang.Boolean) as Lang.String { | ||||
|         var url = Settings.getApiUrl() + "/services/"; | ||||
|         if (s) { | ||||
|             url = url + id.substring(0, id.find(".")) + "/turn_on"; | ||||
|         } else { | ||||
|             url = url + id.substring(0, id.find(".")) + "/turn_off"; | ||||
|         } | ||||
|  | ||||
|         return url; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -16,8 +16,9 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate { | ||||
|         :exit       as Lang.Boolean | ||||
|     }; | ||||
|  | ||||
|     private static var mTimer   as Timer.Timer or Null; | ||||
|     private var mHasToast       as Lang.Boolean = false; | ||||
|     private var mTimer          as Timer.Timer or Null; | ||||
|     private var mConfirmationView   as WatchUi.Confirmation; | ||||
|  | ||||
|     //! Initializes a confirmation delegate to confirm a Wi-Fi or LTE command exection | ||||
|     //! | ||||
| @@ -28,6 +29,7 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate { | ||||
|     //!   - callback: (For type `"entity"`) A callback method (Method<data as Dictionary>) to handle the response. | ||||
|     //!   - data:     (Optional) A dictionary of data to send with the request. | ||||
|     //!   - exit:     Boolean: if set to true: exit after running command. | ||||
|     //! @param view   The Confirmation view the delegate is active for | ||||
|     function initialize(cOptions as { | ||||
|         :type     as Lang.String, | ||||
|         :service  as Lang.String or Null, | ||||
| @@ -35,13 +37,18 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate { | ||||
|         :url      as Lang.String or Null, | ||||
|         :callback as Lang.Method or Null, | ||||
|         :exit     as Lang.Boolean, | ||||
|     }) { | ||||
|     }, view as WatchUi.Confirmation) { | ||||
|         ConfirmationDelegate.initialize(); | ||||
|  | ||||
|         if (mTimer != null) { | ||||
|             mTimer.stop(); | ||||
|         } | ||||
|  | ||||
|         if (WatchUi has :showToast) { | ||||
|             mHasToast = true; | ||||
|         } | ||||
|  | ||||
|         mConfirmationView = view; | ||||
|         mCommandData = { | ||||
|             :type       => cOptions[:type], | ||||
|             :service    => cOptions[:service], | ||||
| @@ -53,7 +60,10 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate { | ||||
|  | ||||
|         var timeout = Settings.getConfirmTimeout(); // ms | ||||
|         if (timeout > 0) { | ||||
|             mTimer = new Timer.Timer(); | ||||
|             if (mTimer == null) { | ||||
|                 mTimer = new Timer.Timer(); | ||||
|             } | ||||
|  | ||||
|             mTimer.start(method(:onTimeout), timeout, true); | ||||
|         } | ||||
|     } | ||||
| @@ -116,6 +126,10 @@ class WifiLteExecutionConfirmDelegate extends WatchUi.ConfirmationDelegate { | ||||
|     //! Function supplied to a timer in order to limit the time for which the confirmation can be provided. | ||||
|     function onTimeout() as Void { | ||||
|         mTimer.stop(); | ||||
|         WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||
|         var getCurrentView = WatchUi.getCurrentView(); | ||||
|  | ||||
|         if (getCurrentView[0] == mConfirmationView) { | ||||
|             WatchUi.popView(WatchUi.SLIDE_RIGHT); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user