@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,463 @@
1
+ package com.rentlytuya.dashboard
2
+
3
+ import android.os.Build
4
+ import android.util.Log
5
+ import androidx.activity.compose.BackHandler
6
+ import androidx.annotation.RequiresApi
7
+ import androidx.compose.foundation.Image
8
+ import androidx.compose.foundation.background
9
+ import androidx.compose.foundation.clickable
10
+ import androidx.compose.foundation.gestures.rememberTransformableState
11
+ import androidx.compose.foundation.gestures.transformable
12
+ import androidx.compose.foundation.layout.Arrangement
13
+ import androidx.compose.foundation.layout.Box
14
+ import androidx.compose.foundation.layout.BoxWithConstraints
15
+ import androidx.compose.foundation.layout.Column
16
+ import androidx.compose.foundation.layout.fillMaxHeight
17
+ import androidx.compose.foundation.layout.fillMaxSize
18
+ import androidx.compose.foundation.layout.fillMaxWidth
19
+ import androidx.compose.foundation.layout.height
20
+ import androidx.compose.foundation.layout.padding
21
+ import androidx.compose.foundation.layout.size
22
+ import androidx.compose.foundation.lazy.LazyColumn
23
+ import androidx.compose.foundation.lazy.LazyListState
24
+ import androidx.compose.foundation.lazy.items
25
+ import androidx.compose.foundation.lazy.rememberLazyListState
26
+ import androidx.compose.material3.IconButton
27
+ import androidx.compose.runtime.Composable
28
+ import androidx.compose.runtime.DisposableEffect
29
+ import androidx.compose.runtime.LaunchedEffect
30
+ import androidx.compose.runtime.MutableLongState
31
+ import androidx.compose.runtime.MutableState
32
+ import androidx.compose.runtime.derivedStateOf
33
+ import androidx.compose.runtime.mutableFloatStateOf
34
+ import androidx.compose.runtime.mutableIntStateOf
35
+ import androidx.compose.runtime.mutableLongStateOf
36
+ import androidx.compose.runtime.mutableStateOf
37
+ import androidx.compose.runtime.remember
38
+ import androidx.compose.runtime.rememberCoroutineScope
39
+ import androidx.compose.ui.Alignment
40
+ import androidx.compose.ui.Modifier
41
+ import androidx.compose.ui.geometry.Offset
42
+ import androidx.compose.ui.graphics.graphicsLayer
43
+ import androidx.compose.ui.platform.LocalConfiguration
44
+ import androidx.compose.ui.res.painterResource
45
+ import androidx.compose.ui.unit.dp
46
+ import androidx.navigation.NavController
47
+ import com.rentlytuya.R
48
+ import com.rentlytuya.components.DatePicker
49
+ import com.rentlytuya.components.Divider
50
+ import com.rentlytuya.components.EncryptedImageView
51
+ import com.rentlytuya.components.Label
52
+ import com.rentlytuya.components.LoadingIndicator
53
+ import com.rentlytuya.tuya.Messages
54
+ import com.rentlytuya.tuya.Tuya
55
+ import com.rentlytuya.tuya.Tuya.TAG
56
+ import com.rentlytuya.ui.theme.LocalColor
57
+ import com.rentlytuya.util.DateUtil.isNotNull
58
+ import com.rentlytuya.util.Heap
59
+ import com.rentlytuya.util.Util
60
+ import com.rentlytuya.util.Util.isLandscape
61
+ import com.rentlytuya.util.Util.strings
62
+ import com.thingclips.smart.ipc.messagecenter.bean.CameraMessageBean
63
+ import kotlinx.coroutines.launch
64
+ import java.time.Instant
65
+ import java.time.LocalDate
66
+ import java.time.ZoneId
67
+ import java.time.format.DateTimeFormatter
68
+ import java.util.Calendar
69
+ import java.util.Date
70
+
71
+ @RequiresApi(Build.VERSION_CODES.O)
72
+ @Composable
73
+ fun Messages(
74
+ isSettings: MutableState<Boolean>,
75
+ isDatePickerVisible: MutableState<Boolean>,
76
+ navController: NavController
77
+ ) {
78
+
79
+ val coroutineScope = rememberCoroutineScope()
80
+ val configuration = LocalConfiguration.current
81
+ val datePickerLoader = remember { mutableStateOf(false) }
82
+ val availableDates = remember { mutableStateOf(emptyArray<Int>()) }
83
+
84
+ val listState = rememberLazyListState()
85
+ val isLoading = remember { mutableStateOf(false) }
86
+ val messages = remember { mutableStateOf<List<CameraMessageBean?>?>(emptyList()) }
87
+ val offset = remember { mutableIntStateOf(0) }
88
+ val noMoreMessages = remember { mutableStateOf(false) }
89
+ val selectedMessage = remember { mutableStateOf<CameraMessageBean?>(null) }
90
+ val selectedDate = remember { mutableLongStateOf(Date().time) }
91
+
92
+ val scrollEndReached = remember {
93
+ derivedStateOf {
94
+ !noMoreMessages.value &&
95
+ (listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index
96
+ ?: 0) >= listState.layoutInfo.totalItemsCount - 1
97
+ }
98
+ }
99
+
100
+ BackHandler {
101
+ isSettings.value = false
102
+ navController.navigate("Dashboard")
103
+ }
104
+
105
+ Column(
106
+ modifier = Modifier
107
+ .fillMaxSize()
108
+ .background(LocalColor.Main.Light),
109
+ horizontalAlignment = Alignment.CenterHorizontally
110
+ ) {
111
+ LaunchedEffect(Unit) {
112
+ Tuya.deviceId?.let {
113
+ Messages.initializeAndFetchMessages(
114
+ offset = offset,
115
+ messages = messages,
116
+ isLoading = isLoading,
117
+ selectedDate = selectedDate,
118
+ noMoreMessages = noMoreMessages
119
+ )
120
+ }
121
+
122
+ val calendar = Calendar.getInstance()
123
+ val currentYear = calendar.get(Calendar.YEAR)
124
+ val currentMonth = calendar.get(Calendar.MONTH) + 1
125
+
126
+ Messages.getAvailableMessageDates(
127
+ year = currentYear,
128
+ month = currentMonth,
129
+ availableDates = availableDates,
130
+ isLoading = datePickerLoader
131
+ )
132
+ }
133
+
134
+ LaunchedEffect(scrollEndReached.value) {
135
+ if (scrollEndReached.value) {
136
+ fetchMoreMessages(
137
+ offset = offset,
138
+ messages = messages,
139
+ isLoading = isLoading,
140
+ selectedDate = selectedDate,
141
+ noMoreMessages = noMoreMessages
142
+ )
143
+ }
144
+ }
145
+
146
+ LaunchedEffect(selectedDate.longValue) {
147
+ offset.intValue = 0
148
+ noMoreMessages.value = false
149
+ messages.value = emptyList()
150
+ listState.scrollToItem(0)
151
+ fetchMoreMessages(
152
+ offset = offset,
153
+ messages = messages,
154
+ isLoading = isLoading,
155
+ selectedDate = selectedDate,
156
+ noMoreMessages = noMoreMessages
157
+ )
158
+ }
159
+
160
+ LaunchedEffect(configuration.orientation) {
161
+ if (isLandscape(configuration) && isDatePickerVisible.value) {
162
+ isDatePickerVisible.value = false
163
+ }
164
+ }
165
+
166
+ DisposableEffect(Unit) {
167
+ onDispose { Messages.destroy() }
168
+ }
169
+
170
+ Box(
171
+ modifier = Modifier
172
+ .fillMaxSize()
173
+ ) {
174
+ when {
175
+ isLoading.value && messages.value.isNullOrEmpty() -> {
176
+ LoadingIndicator()
177
+ }
178
+
179
+ messages.value.isNullOrEmpty() -> {
180
+ NoMessage()
181
+ }
182
+
183
+ else -> {
184
+ MessageList(
185
+ messages = messages.value,
186
+ listState = listState,
187
+ isLoading = isLoading,
188
+ noMoreMessages = noMoreMessages,
189
+ onImageClick = { message ->
190
+ selectedMessage.value = message
191
+ }
192
+ )
193
+ }
194
+ }
195
+
196
+ if (selectedMessage.value.isNotNull()) {
197
+ MessageOverlay(
198
+ message = selectedMessage.value,
199
+ onClose = { selectedMessage.value = null }
200
+ )
201
+ }
202
+ }
203
+
204
+ DatePicker(
205
+ isVisible = isDatePickerVisible,
206
+ availableDates = availableDates.value,
207
+ minDate = if (Tuya.lastMoveOutDate.isNotNull()) LocalDate.parse(
208
+ Tuya.lastMoveOutDate,
209
+ DateTimeFormatter.ISO_DATE_TIME
210
+ ) else null,
211
+ isLoading = datePickerLoader.value,
212
+ onDateSelected = {
213
+
214
+ },
215
+ onMonthChanged = { newMonth ->
216
+ coroutineScope.launch {
217
+ Messages.getAvailableMessageDates(
218
+ year = newMonth.year,
219
+ month = newMonth.monthValue,
220
+ availableDates = availableDates,
221
+ isLoading = datePickerLoader
222
+ )
223
+ }
224
+ },
225
+ onCancel = {
226
+ isDatePickerVisible.value = false
227
+ },
228
+ onOk = { date ->
229
+ selectedDate.longValue = date
230
+ isDatePickerVisible.value = false
231
+ },
232
+ onAppear = {
233
+ val localDate = Instant.ofEpochMilli(selectedDate.longValue)
234
+ .atZone(ZoneId.systemDefault())
235
+ .toLocalDate()
236
+
237
+ coroutineScope.launch {
238
+ Messages.getAvailableMessageDates(
239
+ year = localDate.year,
240
+ month = localDate.monthValue,
241
+ availableDates = availableDates,
242
+ isLoading = datePickerLoader
243
+ )
244
+ }
245
+ }
246
+ )
247
+ }
248
+ }
249
+
250
+ @Composable
251
+ private fun NoMessage() {
252
+ Column(
253
+ modifier = Modifier
254
+ .fillMaxSize(),
255
+ horizontalAlignment = Alignment.CenterHorizontally,
256
+ verticalArrangement = Arrangement.Center
257
+ ) {
258
+ Label(
259
+ modifier = Modifier
260
+ .padding(horizontal = 20.dp),
261
+ title = strings(id = R.string.noMessages),
262
+ bold = true,
263
+ xl18 = true,
264
+ black = true,
265
+ center = true,
266
+ maxLines = 2
267
+ )
268
+ }
269
+ }
270
+
271
+ @Composable
272
+ private fun MessageList(
273
+ messages: List<CameraMessageBean?>?,
274
+ listState: LazyListState,
275
+ isLoading: MutableState<Boolean>,
276
+ noMoreMessages: MutableState<Boolean>,
277
+ onImageClick: (CameraMessageBean) -> Unit
278
+ ) {
279
+ LazyColumn(state = listState) {
280
+ items(messages.orEmpty()) { message ->
281
+ MessageItem(message = message, onImageClick = onImageClick)
282
+ }
283
+
284
+ if (isLoading.value && !noMoreMessages.value) {
285
+ item {
286
+ LoadingIndicator()
287
+ }
288
+ }
289
+ // else if (noMoreMessages.value) {
290
+ // item {
291
+ // Label(
292
+ // title = "To view more messages, adjust filters above.",
293
+ // modifier = Modifier.padding(16.dp)
294
+ // )
295
+ // }
296
+ // }
297
+ }
298
+ }
299
+
300
+ @Composable
301
+ fun MessageItem(
302
+ message: CameraMessageBean?,
303
+ onImageClick: (CameraMessageBean) -> Unit
304
+ ) {
305
+ if (message.isNotNull()) {
306
+ Column(
307
+ modifier = Modifier
308
+ .padding(horizontal = 5.dp)
309
+ ) {
310
+ Column(
311
+ modifier = Modifier
312
+ .fillMaxWidth()
313
+ .padding(top = 8.dp, bottom = 20.dp, start = 35.dp, end = 35.dp),
314
+ horizontalAlignment = Alignment.CenterHorizontally
315
+ ) {
316
+ Column(
317
+ modifier = Modifier
318
+ .fillMaxWidth(),
319
+ horizontalAlignment = Alignment.Start
320
+ ) {
321
+ Label(
322
+ id = message.dateTime,
323
+ title = message.dateTime,
324
+ bold = true,
325
+ m = true,
326
+ black = true,
327
+ medium = true
328
+ )
329
+
330
+ Label(
331
+ modifier = Modifier
332
+ .padding(bottom = if (message.attachPics.isNotNull()) 12.dp else 0.dp),
333
+ id = message.msgContent,
334
+ title = if (message.attachPics.isNotNull()) {
335
+ message.msgContent
336
+ } else {
337
+ strings(id = R.string.unableToCaptureDetectedEvents)
338
+ },
339
+ l = true,
340
+ primary = true,
341
+ semiBold = true,
342
+ maxLines = 6
343
+ )
344
+ }
345
+
346
+ if (message.attachPics.isNotNull()) {
347
+ EncryptedImageView(
348
+ imageUrl = message.attachPics,
349
+ modifier = Modifier
350
+ .fillMaxWidth()
351
+ .height(180.dp)
352
+ .clickable { onImageClick(message) }
353
+ )
354
+ }
355
+ }
356
+
357
+ Divider(thickness = 1.dp)
358
+ }
359
+ }
360
+ }
361
+
362
+ @Composable
363
+ fun MessageOverlay(message: CameraMessageBean?, onClose: () -> Unit) {
364
+
365
+ val configuration = LocalConfiguration.current
366
+
367
+ if (message.isNotNull()) {
368
+ val scale = remember { mutableFloatStateOf(1f) }
369
+ val offset = remember { mutableStateOf(Offset.Zero) }
370
+
371
+ LaunchedEffect(configuration.orientation) {
372
+ scale.floatValue = 1f
373
+ offset.value = Offset.Zero
374
+ }
375
+
376
+ Box(
377
+ modifier = Modifier
378
+ .fillMaxSize()
379
+ .background(color = LocalColor.Monochrome.Black.copy(alpha = 0.9f))
380
+ .clickable(enabled = false, onClick = {})
381
+ ) {
382
+ Column(
383
+ modifier = Modifier
384
+ .align(Alignment.Center)
385
+ ) {
386
+ BoxWithConstraints(
387
+ modifier = Modifier
388
+ .fillMaxWidth(if (Util.isLandscape(configuration)) 0.7f else 1f)
389
+ .fillMaxHeight(if (Util.isLandscape(configuration)) 0.9f else 0.3f)
390
+ ) {
391
+ val state = rememberTransformableState { zoomChange, panChange, _ ->
392
+ scale.floatValue = (scale.floatValue * zoomChange).coerceIn(1f, 5f)
393
+
394
+ val extraWidth = (scale.floatValue - 1) * constraints.maxWidth
395
+ val extraHeight = (scale.floatValue - 1) * constraints.maxHeight
396
+
397
+ val maxX = extraWidth / 2
398
+ val maxY = extraHeight / 2
399
+
400
+ offset.value = Offset(
401
+ x = (offset.value.x + scale.floatValue * panChange.x).coerceIn(-maxX, maxX),
402
+ y = (offset.value.y + scale.floatValue * panChange.y).coerceIn(-maxY, maxY)
403
+ )
404
+ }
405
+
406
+ EncryptedImageView(
407
+ imageUrl = message.attachPics,
408
+ modifier = Modifier
409
+ .fillMaxWidth()
410
+ .fillMaxHeight()
411
+ .graphicsLayer {
412
+ scaleX = scale.floatValue
413
+ scaleY = scale.floatValue
414
+ translationX = offset.value.x
415
+ translationY = offset.value.y
416
+ }
417
+ .transformable(state)
418
+ )
419
+ }
420
+ }
421
+
422
+ IconButton(
423
+ modifier = Modifier
424
+ .align(Alignment.TopEnd)
425
+ .padding(16.dp),
426
+ onClick = {
427
+ Heap.trackEvent(eventName = "Messages_Overlay_Close")
428
+ onClose()
429
+ }
430
+ ) {
431
+ Image(
432
+ modifier = Modifier.size(30.dp),
433
+ painter = painterResource(R.drawable.ic_close),
434
+ contentDescription = "Close"
435
+ )
436
+ }
437
+ }
438
+ }
439
+ }
440
+
441
+ @RequiresApi(Build.VERSION_CODES.O)
442
+ private suspend fun fetchMoreMessages(
443
+ offset: MutableState<Int>,
444
+ messages: MutableState<List<CameraMessageBean?>?>,
445
+ isLoading: MutableState<Boolean>,
446
+ selectedDate: MutableLongState,
447
+ noMoreMessages: MutableState<Boolean>
448
+ ) {
449
+ if (noMoreMessages.value || isLoading.value) return
450
+
451
+ Log.i(
452
+ TAG,
453
+ "Fetching messages ${offset.value} ${noMoreMessages.value} ${isLoading.value} ${messages.value}"
454
+ )
455
+
456
+ Messages.getMessageList(
457
+ offset = offset,
458
+ messages = messages,
459
+ isLoading = isLoading,
460
+ selectedDate = selectedDate,
461
+ noMoreMessages = noMoreMessages
462
+ )
463
+ }