@rentlydev/rently-tuya 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +281 -0
  3. package/android/build.gradle +182 -0
  4. package/android/gradle.properties +7 -0
  5. package/android/libs/airbrake-android-1.4.0.jar +0 -0
  6. package/android/src/main/AndroidManifest.xml +1 -0
  7. package/android/src/main/AndroidManifestNew.xml +25 -0
  8. package/android/src/main/java/com/rentlytuya/RentlyTuyaModule.kt +503 -0
  9. package/android/src/main/java/com/rentlytuya/RentlyTuyaPackage.kt +18 -0
  10. package/android/src/main/java/com/rentlytuya/TuyaActivity.kt +45 -0
  11. package/android/src/main/java/com/rentlytuya/alerts/FormatSDCardAlert.kt +83 -0
  12. package/android/src/main/java/com/rentlytuya/alerts/PermissionAlert.kt +91 -0
  13. package/android/src/main/java/com/rentlytuya/alerts/RemoveDoorbellAlert.kt +83 -0
  14. package/android/src/main/java/com/rentlytuya/alerts/RemoveDoorbellFailureAlert.kt +71 -0
  15. package/android/src/main/java/com/rentlytuya/alerts/ResetWifiAlert.kt +83 -0
  16. package/android/src/main/java/com/rentlytuya/alerts/SuccessAlert.kt +74 -0
  17. package/android/src/main/java/com/rentlytuya/components/Alert.kt +47 -0
  18. package/android/src/main/java/com/rentlytuya/components/AnchorButton.kt +125 -0
  19. package/android/src/main/java/com/rentlytuya/components/Button.kt +147 -0
  20. package/android/src/main/java/com/rentlytuya/components/CustomDatePicker.kt +275 -0
  21. package/android/src/main/java/com/rentlytuya/components/Divider.kt +53 -0
  22. package/android/src/main/java/com/rentlytuya/components/EncryptedImageView.kt +59 -0
  23. package/android/src/main/java/com/rentlytuya/components/Label.kt +155 -0
  24. package/android/src/main/java/com/rentlytuya/components/LoadingIndicator.kt +75 -0
  25. package/android/src/main/java/com/rentlytuya/components/Slider.kt +66 -0
  26. package/android/src/main/java/com/rentlytuya/components/Switch.kt +51 -0
  27. package/android/src/main/java/com/rentlytuya/components/VideoView.kt +45 -0
  28. package/android/src/main/java/com/rentlytuya/dashboard/AdvancedSettings.kt +259 -0
  29. package/android/src/main/java/com/rentlytuya/dashboard/Dashboard.kt +551 -0
  30. package/android/src/main/java/com/rentlytuya/dashboard/DoorbellSettings.kt +874 -0
  31. package/android/src/main/java/com/rentlytuya/dashboard/Messages.kt +463 -0
  32. package/android/src/main/java/com/rentlytuya/dashboard/NavController.kt +358 -0
  33. package/android/src/main/java/com/rentlytuya/dashboard/OfflineScreen.kt +160 -0
  34. package/android/src/main/java/com/rentlytuya/dashboard/Playback.kt +685 -0
  35. package/android/src/main/java/com/rentlytuya/tuya/Messages.kt +234 -0
  36. package/android/src/main/java/com/rentlytuya/tuya/Playback.kt +385 -0
  37. package/android/src/main/java/com/rentlytuya/tuya/ScreenCapture.kt +244 -0
  38. package/android/src/main/java/com/rentlytuya/tuya/Settings.kt +809 -0
  39. package/android/src/main/java/com/rentlytuya/tuya/Tuya.kt +497 -0
  40. package/android/src/main/java/com/rentlytuya/ui/theme/LocalColor.kt +80 -0
  41. package/android/src/main/java/com/rentlytuya/ui/theme/LocalFont.kt +35 -0
  42. package/android/src/main/java/com/rentlytuya/ui/theme/Theme.kt +34 -0
  43. package/android/src/main/java/com/rentlytuya/ui/theme/Type.kt +34 -0
  44. package/android/src/main/java/com/rentlytuya/util/Airbrake.kt +40 -0
  45. package/android/src/main/java/com/rentlytuya/util/DpConstants.kt +53 -0
  46. package/android/src/main/java/com/rentlytuya/util/FrescoManager.kt +86 -0
  47. package/android/src/main/java/com/rentlytuya/util/HeapAnalytics.kt +16 -0
  48. package/android/src/main/java/com/rentlytuya/util/KeylessModule.kt +81 -0
  49. package/android/src/main/java/com/rentlytuya/util/PermissionHandler.kt +75 -0
  50. package/android/src/main/java/com/rentlytuya/util/ReactParamsCheck.kt +152 -0
  51. package/android/src/main/java/com/rentlytuya/util/Util.kt +128 -0
  52. package/android/src/main/res/drawable/ic_close.xml +12 -0
  53. package/android/src/main/res/drawable/ic_launcher_background.xml +170 -0
  54. package/android/src/main/res/drawable/ic_launcher_foreground.xml +30 -0
  55. package/android/src/main/res/drawable/img_place_holder.png +0 -0
  56. package/android/src/main/res/drawable-hdpi/ic_action_arrow_backward.png +0 -0
  57. package/android/src/main/res/drawable-hdpi/ic_arrow_backward_white.png +0 -0
  58. package/android/src/main/res/drawable-hdpi/ic_arrow_blue_right.png +0 -0
  59. package/android/src/main/res/drawable-hdpi/ic_calendar.png +0 -0
  60. package/android/src/main/res/drawable-hdpi/ic_camera.png +0 -0
  61. package/android/src/main/res/drawable-hdpi/ic_message.png +0 -0
  62. package/android/src/main/res/drawable-hdpi/ic_pause.png +0 -0
  63. package/android/src/main/res/drawable-hdpi/ic_play.png +0 -0
  64. package/android/src/main/res/drawable-hdpi/ic_play_back.png +0 -0
  65. package/android/src/main/res/drawable-hdpi/ic_record.png +0 -0
  66. package/android/src/main/res/drawable-hdpi/ic_retry.png +0 -0
  67. package/android/src/main/res/drawable-hdpi/ic_setting.png +0 -0
  68. package/android/src/main/res/drawable-hdpi/ic_sound_off.png +0 -0
  69. package/android/src/main/res/drawable-hdpi/ic_sound_on.png +0 -0
  70. package/android/src/main/res/drawable-mdpi/ic_action_arrow_backward.png +0 -0
  71. package/android/src/main/res/drawable-mdpi/ic_arrow_backward_white.png +0 -0
  72. package/android/src/main/res/drawable-mdpi/ic_arrow_blue_right.png +0 -0
  73. package/android/src/main/res/drawable-mdpi/ic_battery_average.png +0 -0
  74. package/android/src/main/res/drawable-mdpi/ic_battery_charging.png +0 -0
  75. package/android/src/main/res/drawable-mdpi/ic_battery_full.png +0 -0
  76. package/android/src/main/res/drawable-mdpi/ic_battery_good.png +0 -0
  77. package/android/src/main/res/drawable-mdpi/ic_battery_low.png +0 -0
  78. package/android/src/main/res/drawable-mdpi/ic_calendar.png +0 -0
  79. package/android/src/main/res/drawable-mdpi/ic_camera.png +0 -0
  80. package/android/src/main/res/drawable-mdpi/ic_message.png +0 -0
  81. package/android/src/main/res/drawable-mdpi/ic_pause.png +0 -0
  82. package/android/src/main/res/drawable-mdpi/ic_play.png +0 -0
  83. package/android/src/main/res/drawable-mdpi/ic_play_back.png +0 -0
  84. package/android/src/main/res/drawable-mdpi/ic_record.png +0 -0
  85. package/android/src/main/res/drawable-mdpi/ic_retry.png +0 -0
  86. package/android/src/main/res/drawable-mdpi/ic_setting.png +0 -0
  87. package/android/src/main/res/drawable-mdpi/ic_sound_off.png +0 -0
  88. package/android/src/main/res/drawable-mdpi/ic_sound_on.png +0 -0
  89. package/android/src/main/res/drawable-xhdpi/ic_action_arrow_backward.png +0 -0
  90. package/android/src/main/res/drawable-xhdpi/ic_arrow_backward_white.png +0 -0
  91. package/android/src/main/res/drawable-xhdpi/ic_arrow_blue_right.png +0 -0
  92. package/android/src/main/res/drawable-xhdpi/ic_battery_average.png +0 -0
  93. package/android/src/main/res/drawable-xhdpi/ic_battery_charging.png +0 -0
  94. package/android/src/main/res/drawable-xhdpi/ic_battery_full.png +0 -0
  95. package/android/src/main/res/drawable-xhdpi/ic_battery_good.png +0 -0
  96. package/android/src/main/res/drawable-xhdpi/ic_battery_low.png +0 -0
  97. package/android/src/main/res/drawable-xhdpi/ic_calendar.png +0 -0
  98. package/android/src/main/res/drawable-xhdpi/ic_camera.png +0 -0
  99. package/android/src/main/res/drawable-xhdpi/ic_message.png +0 -0
  100. package/android/src/main/res/drawable-xhdpi/ic_pause.png +0 -0
  101. package/android/src/main/res/drawable-xhdpi/ic_play.png +0 -0
  102. package/android/src/main/res/drawable-xhdpi/ic_play_back.png +0 -0
  103. package/android/src/main/res/drawable-xhdpi/ic_record.png +0 -0
  104. package/android/src/main/res/drawable-xhdpi/ic_retry.png +0 -0
  105. package/android/src/main/res/drawable-xhdpi/ic_setting.png +0 -0
  106. package/android/src/main/res/drawable-xhdpi/ic_sound_off.png +0 -0
  107. package/android/src/main/res/drawable-xhdpi/ic_sound_on.png +0 -0
  108. package/android/src/main/res/drawable-xxhdpi/ic_action_arrow_backward.png +0 -0
  109. package/android/src/main/res/drawable-xxhdpi/ic_arrow_backward_white.png +0 -0
  110. package/android/src/main/res/drawable-xxhdpi/ic_arrow_blue_right.png +0 -0
  111. package/android/src/main/res/drawable-xxhdpi/ic_battery_average.png +0 -0
  112. package/android/src/main/res/drawable-xxhdpi/ic_battery_charging.png +0 -0
  113. package/android/src/main/res/drawable-xxhdpi/ic_battery_full.png +0 -0
  114. package/android/src/main/res/drawable-xxhdpi/ic_battery_good.png +0 -0
  115. package/android/src/main/res/drawable-xxhdpi/ic_battery_low.png +0 -0
  116. package/android/src/main/res/drawable-xxhdpi/ic_calendar.png +0 -0
  117. package/android/src/main/res/drawable-xxhdpi/ic_camera.png +0 -0
  118. package/android/src/main/res/drawable-xxhdpi/ic_message.png +0 -0
  119. package/android/src/main/res/drawable-xxhdpi/ic_pause.png +0 -0
  120. package/android/src/main/res/drawable-xxhdpi/ic_play.png +0 -0
  121. package/android/src/main/res/drawable-xxhdpi/ic_play_back.png +0 -0
  122. package/android/src/main/res/drawable-xxhdpi/ic_record.png +0 -0
  123. package/android/src/main/res/drawable-xxhdpi/ic_retry.png +0 -0
  124. package/android/src/main/res/drawable-xxhdpi/ic_setting.png +0 -0
  125. package/android/src/main/res/drawable-xxhdpi/ic_sound_off.png +0 -0
  126. package/android/src/main/res/drawable-xxhdpi/ic_sound_on.png +0 -0
  127. package/android/src/main/res/drawable-xxxhdpi/ic_action_arrow_backward.png +0 -0
  128. package/android/src/main/res/drawable-xxxhdpi/ic_arrow_backward_white.png +0 -0
  129. package/android/src/main/res/drawable-xxxhdpi/ic_arrow_blue_right.png +0 -0
  130. package/android/src/main/res/drawable-xxxhdpi/ic_calendar.png +0 -0
  131. package/android/src/main/res/drawable-xxxhdpi/ic_camera.png +0 -0
  132. package/android/src/main/res/drawable-xxxhdpi/ic_message.png +0 -0
  133. package/android/src/main/res/drawable-xxxhdpi/ic_pause.png +0 -0
  134. package/android/src/main/res/drawable-xxxhdpi/ic_play.png +0 -0
  135. package/android/src/main/res/drawable-xxxhdpi/ic_play_back.png +0 -0
  136. package/android/src/main/res/drawable-xxxhdpi/ic_record.png +0 -0
  137. package/android/src/main/res/drawable-xxxhdpi/ic_retry.png +0 -0
  138. package/android/src/main/res/drawable-xxxhdpi/ic_setting.png +0 -0
  139. package/android/src/main/res/drawable-xxxhdpi/ic_sound_off.png +0 -0
  140. package/android/src/main/res/drawable-xxxhdpi/ic_sound_on.png +0 -0
  141. package/android/src/main/res/font/quicksand_bold.ttf +0 -0
  142. package/android/src/main/res/font/quicksand_light.ttf +0 -0
  143. package/android/src/main/res/font/quicksand_medium.ttf +0 -0
  144. package/android/src/main/res/font/quicksand_regular.ttf +0 -0
  145. package/android/src/main/res/font/quicksand_semi_bold.ttf +0 -0
  146. package/android/src/main/res/values/strings.xml +121 -0
  147. package/android/thingMapping.gradle +200 -0
  148. package/android/thingMapping.json +2014 -0
  149. package/ios/components/Alert.swift +54 -0
  150. package/ios/components/AnchorButton.swift +100 -0
  151. package/ios/components/Button.swift +118 -0
  152. package/ios/components/CustomDatePicker.swift +275 -0
  153. package/ios/components/Divider.swift +28 -0
  154. package/ios/components/Image.swift +72 -0
  155. package/ios/components/Label.swift +105 -0
  156. package/ios/components/Switch.swift +61 -0
  157. package/ios/dashboard/AdvanceSettings.swift +127 -0
  158. package/ios/dashboard/Dashboard.swift +354 -0
  159. package/ios/dashboard/Messages.swift +361 -0
  160. package/ios/dashboard/NavigationController.swift +173 -0
  161. package/ios/dashboard/OfflineScreen.swift +109 -0
  162. package/ios/dashboard/Playback.swift +543 -0
  163. package/ios/dashboard/PreviewManager.swift +117 -0
  164. package/ios/dashboard/Settings.swift +672 -0
  165. package/ios/icons/Charging.png +0 -0
  166. package/ios/icons/Charging@2x.png +0 -0
  167. package/ios/icons/Charging@3x.png +0 -0
  168. package/ios/icons/back_arraow.png +0 -0
  169. package/ios/icons/back_arraow@2x.png +0 -0
  170. package/ios/icons/back_arraow@3x.png +0 -0
  171. package/ios/icons/battery_average.png +0 -0
  172. package/ios/icons/battery_average@2x.png +0 -0
  173. package/ios/icons/battery_average@3x.png +0 -0
  174. package/ios/icons/battery_full.png +0 -0
  175. package/ios/icons/battery_full@2x.png +0 -0
  176. package/ios/icons/battery_full@3x.png +0 -0
  177. package/ios/icons/battery_good.png +0 -0
  178. package/ios/icons/battery_good@2x.png +0 -0
  179. package/ios/icons/battery_good@3x.png +0 -0
  180. package/ios/icons/battery_low.png +0 -0
  181. package/ios/icons/battery_low@2x.png +0 -0
  182. package/ios/icons/battery_low@3x.png +0 -0
  183. package/ios/icons/calendar.png +0 -0
  184. package/ios/icons/calendar@2x.png +0 -0
  185. package/ios/icons/calendar@3x.png +0 -0
  186. package/ios/icons/cloud.png +0 -0
  187. package/ios/icons/cloud@2x.png +0 -0
  188. package/ios/icons/cloud@3x.png +0 -0
  189. package/ios/icons/down_update.png +0 -0
  190. package/ios/icons/down_update@2x.png +0 -0
  191. package/ios/icons/down_update@3x.png +0 -0
  192. package/ios/icons/exit_fullscreen.png +0 -0
  193. package/ios/icons/exit_fullscreen@2x.png +0 -0
  194. package/ios/icons/exit_fullscreen@3x.png +0 -0
  195. package/ios/icons/expand.png +0 -0
  196. package/ios/icons/fullscreen.png +0 -0
  197. package/ios/icons/fullscreen@2x.png +0 -0
  198. package/ios/icons/fullscreen@3x.png +0 -0
  199. package/ios/icons/image_placeholder.png +0 -0
  200. package/ios/icons/information.png +0 -0
  201. package/ios/icons/information@2x.png +0 -0
  202. package/ios/icons/information@3x.png +0 -0
  203. package/ios/icons/keyless_Setting.png +0 -0
  204. package/ios/icons/keyless_Setting@2x.png +0 -0
  205. package/ios/icons/keyless_Setting@3x.png +0 -0
  206. package/ios/icons/keyless_back@1x.png +0 -0
  207. package/ios/icons/keyless_back@2x.png +0 -0
  208. package/ios/icons/keyless_back@3x.png +0 -0
  209. package/ios/icons/keyless_filter.png +0 -0
  210. package/ios/icons/keyless_filter@2x.png +0 -0
  211. package/ios/icons/keyless_filter@3x.png +0 -0
  212. package/ios/icons/keyless_message.png +0 -0
  213. package/ios/icons/keyless_message@2x.png +0 -0
  214. package/ios/icons/keyless_message@3x.png +0 -0
  215. package/ios/icons/keyless_pause.png +0 -0
  216. package/ios/icons/keyless_pause@2x.png +0 -0
  217. package/ios/icons/keyless_pause@3x.png +0 -0
  218. package/ios/icons/keyless_photo.png +0 -0
  219. package/ios/icons/keyless_photo@2x.png +0 -0
  220. package/ios/icons/keyless_photo@3x.png +0 -0
  221. package/ios/icons/keyless_play.png +0 -0
  222. package/ios/icons/keyless_play@2x.png +0 -0
  223. package/ios/icons/keyless_play@3x.png +0 -0
  224. package/ios/icons/keyless_play_list.png +0 -0
  225. package/ios/icons/keyless_play_list@2x.png +0 -0
  226. package/ios/icons/keyless_play_list@3x.png +0 -0
  227. package/ios/icons/keyless_play_playback.png +0 -0
  228. package/ios/icons/keyless_play_playback@2x.png +0 -0
  229. package/ios/icons/keyless_play_playback@3x.png +0 -0
  230. package/ios/icons/keyless_record.png +0 -0
  231. package/ios/icons/keyless_record@2x.png +0 -0
  232. package/ios/icons/keyless_record@3x.png +0 -0
  233. package/ios/icons/keyless_record_on.png +0 -0
  234. package/ios/icons/keyless_record_on@2x.png +0 -0
  235. package/ios/icons/keyless_record_on@3x.png +0 -0
  236. package/ios/icons/keyless_sound_off.png +0 -0
  237. package/ios/icons/keyless_sound_off@2x.png +0 -0
  238. package/ios/icons/keyless_sound_off@3x.png +0 -0
  239. package/ios/icons/keyless_sound_on.png +0 -0
  240. package/ios/icons/keyless_sound_on@2x.png +0 -0
  241. package/ios/icons/keyless_sound_on@3x.png +0 -0
  242. package/ios/icons/keyless_speak_off.png +0 -0
  243. package/ios/icons/keyless_speak_off@2x.png +0 -0
  244. package/ios/icons/keyless_speak_on.png +0 -0
  245. package/ios/icons/keyless_speak_on@2x.png +0 -0
  246. package/ios/icons/keyless_speak_on@3x.png +0 -0
  247. package/ios/icons/refresh.png +0 -0
  248. package/ios/icons/refresh@2x.png +0 -0
  249. package/ios/icons/refresh@3x.png +0 -0
  250. package/ios/icons/ty_camera_control_hd_normal@2x.png +0 -0
  251. package/ios/icons/ty_camera_control_hd_normal@3x.png +0 -0
  252. package/ios/icons/ty_camera_control_sd_normal@2x.png +0 -0
  253. package/ios/icons/ty_camera_control_sd_normal@3x.png +0 -0
  254. package/ios/icons/upgrade_success.png +0 -0
  255. package/ios/icons/upgrade_success@2x.png +0 -0
  256. package/ios/icons/upgrade_success@3x.png +0 -0
  257. package/ios/listener/KeylessListener.m +8 -0
  258. package/ios/listener/KeylessListener.swift +56 -0
  259. package/ios/listener/RentlyTuya-Bridging-Header.h +5 -0
  260. package/ios/listener/RentlyTuya.mm +56 -0
  261. package/ios/listener/RentlyTuya.swift +544 -0
  262. package/ios/theme/LocalColor.swift +33 -0
  263. package/ios/theme/LocalFont.swift +32 -0
  264. package/ios/theme/Theme.swift +71 -0
  265. package/ios/tuya/CameraManager.swift +296 -0
  266. package/ios/tuya/SettingsManager.swift +475 -0
  267. package/ios/tuya/Tuya.swift +570 -0
  268. package/ios/tuya/TuyaMessages.swift +98 -0
  269. package/ios/utils/Airbrake.swift +31 -0
  270. package/ios/utils/AppUtility.swift +76 -0
  271. package/ios/utils/HeapAnalytics.swift +8 -0
  272. package/ios/utils/OrientationManager.swift +60 -0
  273. package/ios/utils/PromiseHandler.swift +36 -0
  274. package/lib/commonjs/index.js +90 -0
  275. package/lib/commonjs/index.js.map +1 -0
  276. package/lib/commonjs/package.json +1 -0
  277. package/lib/module/index.js +83 -0
  278. package/lib/module/index.js.map +1 -0
  279. package/lib/module/package.json +1 -0
  280. package/lib/typescript/commonjs/package.json +1 -0
  281. package/lib/typescript/commonjs/src/index.d.ts +75 -0
  282. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  283. package/lib/typescript/module/package.json +1 -0
  284. package/lib/typescript/module/src/index.d.ts +75 -0
  285. package/lib/typescript/module/src/index.d.ts.map +1 -0
  286. package/package.json +188 -0
  287. package/rently-tuya.podspec +52 -0
  288. package/src/index.tsx +158 -0
@@ -0,0 +1,551 @@
1
+ package com.rentlytuya.dashboard
2
+
3
+ import android.Manifest
4
+ import android.app.Activity
5
+ import android.util.Log
6
+ import androidx.activity.compose.BackHandler
7
+ import androidx.compose.animation.AnimatedVisibility
8
+ import androidx.compose.animation.fadeIn
9
+ import androidx.compose.animation.fadeOut
10
+ import androidx.compose.foundation.Image
11
+ import androidx.compose.foundation.background
12
+ import androidx.compose.foundation.clickable
13
+ import androidx.compose.foundation.layout.Arrangement
14
+ import androidx.compose.foundation.layout.Box
15
+ import androidx.compose.foundation.layout.BoxScope
16
+ import androidx.compose.foundation.layout.Column
17
+ import androidx.compose.foundation.layout.Row
18
+ import androidx.compose.foundation.layout.fillMaxHeight
19
+ import androidx.compose.foundation.layout.fillMaxSize
20
+ import androidx.compose.foundation.layout.fillMaxWidth
21
+ import androidx.compose.foundation.layout.height
22
+ import androidx.compose.foundation.layout.padding
23
+ import androidx.compose.foundation.layout.size
24
+ import androidx.compose.foundation.layout.width
25
+ import androidx.compose.foundation.shape.RoundedCornerShape
26
+ import androidx.compose.runtime.Composable
27
+ import androidx.compose.runtime.DisposableEffect
28
+ import androidx.compose.runtime.LaunchedEffect
29
+ import androidx.compose.runtime.MutableIntState
30
+ import androidx.compose.runtime.MutableState
31
+ import androidx.compose.runtime.mutableIntStateOf
32
+ import androidx.compose.runtime.mutableStateOf
33
+ import androidx.compose.runtime.remember
34
+ import androidx.compose.runtime.rememberCoroutineScope
35
+ import androidx.compose.ui.Alignment
36
+ import androidx.compose.ui.Modifier
37
+ import androidx.compose.ui.draw.clip
38
+ import androidx.compose.ui.platform.LocalConfiguration
39
+ import androidx.compose.ui.platform.LocalContext
40
+ import androidx.compose.ui.res.painterResource
41
+ import androidx.compose.ui.unit.dp
42
+ import androidx.lifecycle.Lifecycle
43
+ import androidx.lifecycle.LifecycleEventObserver
44
+ import androidx.lifecycle.compose.LocalLifecycleOwner
45
+ import androidx.navigation.NavController
46
+ import com.rentlytuya.R
47
+ import com.rentlytuya.alerts.PermissionAlert
48
+ import com.rentlytuya.alerts.SuccessAlert
49
+ import com.rentlytuya.components.Button
50
+ import com.rentlytuya.components.Label
51
+ import com.rentlytuya.components.LoadingIndicator
52
+ import com.rentlytuya.components.VideoView
53
+ import com.rentlytuya.tuya.ScreenCapture
54
+ import com.rentlytuya.tuya.Settings
55
+ import com.rentlytuya.tuya.Tuya
56
+ import com.rentlytuya.tuya.Tuya.TAG
57
+ import com.rentlytuya.ui.theme.LocalColor
58
+ import com.rentlytuya.util.Heap
59
+ import com.rentlytuya.util.PermissionHandler
60
+ import com.rentlytuya.util.Util.isLandscape
61
+ import com.rentlytuya.util.Util.strings
62
+ import kotlinx.coroutines.delay
63
+ import kotlinx.coroutines.launch
64
+
65
+ @Composable
66
+ fun Dashboard(
67
+ modifier: Modifier,
68
+ navController: NavController,
69
+ isMuted: MutableState<Boolean>,
70
+ isOnline: MutableState<Boolean>,
71
+ isRecording: MutableState<Boolean>,
72
+ powerSource: MutableState<String>,
73
+ batteryPercentage: MutableIntState
74
+ ) {
75
+ Box(
76
+ modifier = Modifier
77
+ .fillMaxSize()
78
+ .background(LocalColor.Monochrome.Black)
79
+ .then(modifier)
80
+ ) {
81
+ val context = LocalContext.current
82
+ val activity = LocalContext.current as Activity
83
+ val configuration = LocalConfiguration.current
84
+ val scope = rememberCoroutineScope()
85
+ val lifecycleOwner = LocalLifecycleOwner.current
86
+
87
+ val isMicOn = remember { mutableStateOf(false) }
88
+ val previewLoader = remember { mutableStateOf(false) }
89
+ val isLoading = remember { mutableStateOf(false) }
90
+ val videoType = remember { mutableIntStateOf(4) }
91
+ val isPermissionDisclaimerAlertVisible = remember { mutableStateOf(false) }
92
+ val isScreenShotSuccess = remember { mutableStateOf(false) }
93
+ val isRecordingSuccess = remember { mutableStateOf(false) }
94
+ val isRecordingFailure = remember { mutableStateOf(false) }
95
+ val isDoorbellControlVisible = remember { mutableStateOf(true) }
96
+
97
+ val permissions = arrayOf(
98
+ Manifest.permission.RECORD_AUDIO,
99
+ )
100
+
101
+ LaunchedEffect(configuration.orientation, isDoorbellControlVisible.value) {
102
+ if (isLandscape(configuration) && isDoorbellControlVisible.value) {
103
+ delay(3000)
104
+ isDoorbellControlVisible.value = false
105
+ }
106
+
107
+ if (!isLandscape(configuration)) {
108
+ isDoorbellControlVisible.value = true
109
+ }
110
+ }
111
+
112
+ PermissionAlert(
113
+ context = context,
114
+ permissions = permissions,
115
+ isPermissionDisclaimerAlertVisible = isPermissionDisclaimerAlertVisible.value
116
+ ) {
117
+ isPermissionDisclaimerAlertVisible.value = false
118
+ }
119
+
120
+ SuccessAlert(
121
+ title = strings(id = R.string.success),
122
+ description = strings(id = R.string.videoSuccess),
123
+ isVisible = isRecordingSuccess.value
124
+ ) {
125
+ isRecordingSuccess.value = false
126
+ }
127
+
128
+ SuccessAlert(
129
+ title = strings(id = R.string.failure),
130
+ description = strings(id = R.string.videoFailure),
131
+ isVisible = isRecordingFailure.value
132
+ ) {
133
+ isRecordingFailure.value = false
134
+ }
135
+
136
+ SuccessAlert(
137
+ title = strings(id = R.string.success),
138
+ description = strings(id = R.string.screenshotSuccess),
139
+ isVisible = isScreenShotSuccess.value
140
+ ) {
141
+ isScreenShotSuccess.value = false
142
+ }
143
+
144
+ BackHandler {
145
+ scope.launch {
146
+ val success = Tuya.disconnect { value -> isLoading.value = value }
147
+ if (!success) {
148
+ Log.i(TAG, "Not Disconnected but still navigating the user to React Native")
149
+ }
150
+ activity.finish()
151
+ }
152
+ }
153
+
154
+ DisposableEffect(lifecycleOwner) {
155
+ val observer = LifecycleEventObserver { _, event ->
156
+ if (event == Lifecycle.Event.ON_RESUME) {
157
+ scope.launch {
158
+ Tuya.connectAndStartPreview(
159
+ // TODO:: Check for an alternative to identify whether it is connected or not
160
+ setOnline = { value ->
161
+ isOnline.value = value
162
+ },
163
+ setMute = { value ->
164
+ isMuted.value = value
165
+ },
166
+ setLoading = { value ->
167
+ previewLoader.value = value
168
+ }
169
+ )
170
+ }
171
+ }
172
+ }
173
+ lifecycleOwner.lifecycle.addObserver(observer)
174
+ onDispose {
175
+ lifecycleOwner.lifecycle.removeObserver(observer)
176
+ }
177
+ }
178
+
179
+ Column(
180
+ modifier = Modifier
181
+ .fillMaxSize()
182
+ ) {
183
+ Preview(
184
+ previewLoader = previewLoader,
185
+ isOnline = isOnline,
186
+ isMuted = isMuted,
187
+ isDoorbellControlVisible = isDoorbellControlVisible
188
+ )
189
+ }
190
+
191
+ if (isOnline.value) {
192
+ DoorbellControls(
193
+ permissions = permissions,
194
+ isDoorbellControlVisible = isDoorbellControlVisible.value,
195
+ videoType = videoType,
196
+ isMicOn = isMicOn,
197
+ isMuted = isMuted,
198
+ isLoading = isLoading,
199
+ isPermissionDisclaimerAlertVisible = isPermissionDisclaimerAlertVisible,
200
+ powerSource = powerSource,
201
+ batteryPercentage = batteryPercentage
202
+ )
203
+ }
204
+
205
+ if (!isLandscape(configuration)) {
206
+ BottomNavigationBar(
207
+ navController = navController,
208
+ isMuted = isMuted,
209
+ isOnline = isOnline,
210
+ isRecording = isRecording,
211
+ isRecordingSuccess = isRecordingSuccess,
212
+ isRecordingFailure = isRecordingFailure,
213
+ isScreenShotSuccess = isScreenShotSuccess
214
+ )
215
+ }
216
+ }
217
+ }
218
+
219
+ @Composable
220
+ fun Preview(
221
+ previewLoader: MutableState<Boolean>,
222
+ isOnline: MutableState<Boolean>,
223
+ isMuted: MutableState<Boolean>,
224
+ isDoorbellControlVisible: MutableState<Boolean>
225
+ ) {
226
+ val scope = rememberCoroutineScope()
227
+
228
+ fun reConnect() {
229
+ scope.launch {
230
+ Tuya.connectAndStartPreview(
231
+ // TODO:: Check for an alternative to identify whether it is connected or not
232
+ setOnline = { value ->
233
+ isOnline.value = value
234
+ },
235
+ setMute = { value ->
236
+ isMuted.value = value
237
+ },
238
+ setLoading = { value ->
239
+ previewLoader.value = value
240
+ }
241
+ )
242
+ }
243
+ }
244
+
245
+ Row(
246
+ modifier = Modifier
247
+ .fillMaxWidth()
248
+ .fillMaxHeight(0.9f)
249
+ .background(LocalColor.Monochrome.Black),
250
+ horizontalArrangement = Arrangement.Center,
251
+ verticalAlignment = Alignment.CenterVertically
252
+ ) {
253
+ when {
254
+ previewLoader.value -> LoadingIndicator()
255
+ !isOnline.value -> OfflineScreen(onReConnect = { reConnect() })
256
+ else -> Box(
257
+ modifier = Modifier
258
+ .fillMaxWidth()
259
+ ) {
260
+ VideoView(modifier = Modifier.fillMaxSize()) {
261
+ isDoorbellControlVisible.value = true
262
+ }
263
+ }
264
+ }
265
+ }
266
+ }
267
+
268
+ @Composable
269
+ fun BoxScope.DoorbellControls(
270
+ isDoorbellControlVisible: Boolean,
271
+ permissions: Array<String>,
272
+ videoType: MutableState<Int>,
273
+ isMicOn: MutableState<Boolean>,
274
+ isMuted: MutableState<Boolean>,
275
+ isLoading: MutableState<Boolean>,
276
+ isPermissionDisclaimerAlertVisible: MutableState<Boolean>,
277
+ powerSource: MutableState<String>,
278
+ batteryPercentage: MutableIntState
279
+ ) {
280
+
281
+ val context = LocalContext.current
282
+ val configuration = LocalConfiguration.current
283
+
284
+ AnimatedVisibility(
285
+ visible = !isLandscape(configuration) || isDoorbellControlVisible,
286
+ enter = fadeIn(),
287
+ exit = fadeOut(),
288
+ modifier = Modifier
289
+ .fillMaxWidth()
290
+ .align(Alignment.BottomCenter)
291
+ ) {
292
+
293
+ if (!Settings.is8s()) {
294
+ Row(
295
+ modifier = Modifier
296
+ .fillMaxWidth()
297
+ .padding(horizontal = 30.dp, vertical = 4.dp),
298
+ verticalAlignment = Alignment.CenterVertically,
299
+ ) {
300
+ val batteryIcon = when {
301
+ powerSource.value == "0" -> {
302
+ when {
303
+ batteryPercentage.intValue > 90 -> R.drawable.ic_battery_full
304
+ batteryPercentage.intValue >= 75 -> R.drawable.ic_battery_good
305
+ batteryPercentage.intValue >= 40 -> R.drawable.ic_battery_average
306
+ else -> R.drawable.ic_battery_low
307
+ }
308
+ }
309
+
310
+ else -> R.drawable.ic_battery_charging
311
+ }
312
+
313
+ Image(
314
+ painter = painterResource(id = batteryIcon),
315
+ contentDescription = "Battery Icon",
316
+ modifier = Modifier.size(24.dp)
317
+ )
318
+
319
+ Label(
320
+ modifier = Modifier
321
+ .padding(start = 4.dp),
322
+ title = if (powerSource.value == "0") {
323
+ "${batteryPercentage.intValue}%"
324
+ } else {
325
+ strings(id = R.string.charging)
326
+ },
327
+ white = true,
328
+ s = true
329
+ )
330
+ }
331
+ }
332
+
333
+ Box(
334
+ modifier = Modifier
335
+ .padding(top = 30.dp, bottom = if (isLandscape(configuration)) 24.dp else 96.dp)
336
+ ) {
337
+
338
+ Box(
339
+ modifier = Modifier
340
+ .align(Alignment.CenterStart)
341
+ .padding(start = 25.dp)
342
+ ) {
343
+ Button(
344
+ modifier = Modifier
345
+ .width(60.dp)
346
+ .height(30.dp),
347
+ id = "Toggle to ${if (videoType.value == 2) "SD" else "HD"}",
348
+ title = if (videoType.value == 2) strings(id = R.string.sd) else strings(id = R.string.hd),
349
+ s = true,
350
+ semiBold = true,
351
+ grey = true,
352
+ disabled = isLoading.value,
353
+ textColor = LocalColor.Monochrome.White,
354
+ cornerRadius = 20.dp,
355
+ onClick = {
356
+ Tuya.changeResolution(
357
+ videoId = if (videoType.value == 2) 4 else 2,
358
+ setVideoType = { value -> videoType.value = value },
359
+ setLoading = { value -> isLoading.value = value },
360
+ )
361
+ }
362
+ )
363
+ }
364
+
365
+ val mainButtonModifier = Modifier
366
+ .width(160.dp)
367
+ .height(50.dp)
368
+ .align(Alignment.Center)
369
+
370
+ Button(
371
+ modifier = mainButtonModifier,
372
+ id = "Toggle to ${if (isMicOn.value) "Tap to mute" else "Tap to speak"}",
373
+ title = if (isMicOn.value) strings(id = R.string.tapToMute) else strings(id = R.string.tapToSpeak),
374
+ grey = !isMicOn.value,
375
+ medium = isMicOn.value,
376
+ semiBold = true,
377
+ disabled = isLoading.value,
378
+ textColor = LocalColor.Monochrome.White,
379
+ cornerRadius = 40.dp,
380
+ onClick = {
381
+ if (PermissionHandler.arePermissionsGranted(context, permissions)) {
382
+ if (isMicOn.value) {
383
+ Tuya.stopVoiceTalk(
384
+ setMic = { value -> isMicOn.value = value },
385
+ setLoading = { value -> isLoading.value = value },
386
+ )
387
+ } else {
388
+ // The speaker needs to be un muted when the mic is turned on.
389
+ if (isMuted.value) {
390
+ Tuya.setMute(
391
+ mute = 0,
392
+ setMute = { value ->
393
+ isMuted.value = value
394
+ }
395
+ )
396
+ }
397
+ Tuya.startVoiceTalk(
398
+ context = context,
399
+ setMic = { value -> isMicOn.value = value },
400
+ setLoading = { value -> isLoading.value = value },
401
+ )
402
+ }
403
+ } else {
404
+ isPermissionDisclaimerAlertVisible.value = true
405
+ }
406
+ }
407
+ )
408
+ }
409
+ }
410
+ }
411
+
412
+ @Composable
413
+ fun BoxScope.BottomNavigationBar(
414
+ navController: NavController,
415
+ isMuted: MutableState<Boolean>,
416
+ isOnline: MutableState<Boolean>,
417
+ isRecording: MutableState<Boolean>,
418
+ isScreenShotSuccess: MutableState<Boolean>,
419
+ isRecordingSuccess: MutableState<Boolean>,
420
+ isRecordingFailure: MutableState<Boolean>
421
+ ) {
422
+
423
+ val context = LocalContext.current
424
+ val scope = rememberCoroutineScope()
425
+
426
+ Row(
427
+ modifier = Modifier
428
+ .fillMaxWidth()
429
+ .background(LocalColor.Monochrome.Grey)
430
+ .align(Alignment.BottomCenter),
431
+ verticalAlignment = Alignment.CenterVertically,
432
+ horizontalArrangement = Arrangement.SpaceEvenly
433
+ ) {
434
+ SettingsButton(
435
+ modifier = if (!isMuted.value) {
436
+ Modifier.background(LocalColor.Primary.Dark)
437
+ } else {
438
+ Modifier
439
+ },
440
+ imageId = if (isMuted.value) {
441
+ R.drawable.ic_sound_off
442
+ } else {
443
+ R.drawable.ic_sound_on
444
+ },
445
+ event = if (!isMuted.value) "Dashboard_SpeakerOff" else "Dashboard_SpeakerOn"
446
+ ) {
447
+ if (isOnline.value) {
448
+ Tuya.setMute(
449
+ if (isMuted.value) {
450
+ 0
451
+ } else {
452
+ 1
453
+ }, setMute = { value ->
454
+ isMuted.value = value
455
+ }
456
+ )
457
+ }
458
+ }
459
+
460
+ SettingsButton(
461
+ imageId = R.drawable.ic_camera,
462
+ event = "Dashboard_Screenshot"
463
+ ) {
464
+ scope.launch {
465
+ val status = ScreenCapture.screenShot(
466
+ context = context
467
+ )
468
+ if (status) {
469
+ isScreenShotSuccess.value = true
470
+ }
471
+ }
472
+ }
473
+
474
+ SettingsButton(
475
+ modifier = if (isRecording.value) {
476
+ Modifier.background(LocalColor.Danger.Primary)
477
+ } else {
478
+ Modifier
479
+ },
480
+ imageId = R.drawable.ic_record,
481
+ event = if (!isRecording.value) "Dashboard_StartRecording" else "Dashboard_StopRecording"
482
+ ) {
483
+ if (!isRecording.value) {
484
+ ScreenCapture.startRecording(
485
+ context = context
486
+ ) { value ->
487
+ isRecording.value = value
488
+ }
489
+ } else {
490
+ scope.launch {
491
+ val status = ScreenCapture.stopRecording(
492
+ context = context
493
+ ) { value ->
494
+ isRecording.value = value
495
+ }
496
+ if (status) {
497
+ isRecordingSuccess.value = true
498
+ } else {
499
+ isRecordingFailure.value = true
500
+ }
501
+ }
502
+ }
503
+ }
504
+
505
+ SettingsButton(imageId = R.drawable.ic_play_back, event = "Playback") {
506
+ if (isRecording.value) {
507
+ scope.launch {
508
+ val status = ScreenCapture.stopRecording(
509
+ context = context
510
+ ) { value ->
511
+ isRecording.value = value
512
+ }
513
+ if (status) {
514
+ isRecordingSuccess.value = true
515
+ } else {
516
+ isRecordingFailure.value = true
517
+ }
518
+ }
519
+ } else {
520
+ navController.navigate("Playback")
521
+ }
522
+ }
523
+
524
+ SettingsButton(imageId = R.drawable.ic_message, event = "Messages") {
525
+ navController.navigate("Messages")
526
+ }
527
+ }
528
+ }
529
+
530
+ @Composable
531
+ fun SettingsButton(
532
+ modifier: Modifier = Modifier,
533
+ imageId: Int,
534
+ event: String,
535
+ onClick: () -> Unit
536
+ ) {
537
+ Image(
538
+ modifier = Modifier
539
+ .padding(vertical = 5.dp)
540
+ .clip(RoundedCornerShape(70.dp))
541
+ .size(50.dp)
542
+ .then(modifier)
543
+ .clickable {
544
+ Heap.trackEvent(eventName = event)
545
+ onClick()
546
+ }
547
+ .padding(10.dp),
548
+ painter = painterResource(id = imageId),
549
+ contentDescription = "settingsIcon"
550
+ )
551
+ }