@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,672 @@
1
+ import SwiftUI
2
+ import ThingSmartCameraBase
3
+ import ThingSmartDeviceKit
4
+ import ThingSmartCameraKit
5
+
6
+ enum NightVision: String, CaseIterable {
7
+ case auto = "0"
8
+ case off = "1"
9
+ case on = "2"
10
+
11
+ var displayText: String {
12
+ switch self {
13
+ case .auto: return "Auto"
14
+ case .off: return "Off"
15
+ case .on: return "On"
16
+ }
17
+ }
18
+ }
19
+
20
+ enum MotionSensitivityLevel: String, CaseIterable {
21
+ case low = "0"
22
+ case medium = "1"
23
+ case high = "2"
24
+
25
+ var displayText: String {
26
+ switch self {
27
+ case .low: return "Low"
28
+ case .medium: return "Medium"
29
+ case .high: return "High"
30
+ }
31
+ }
32
+ }
33
+
34
+ enum PIRSensitivityLevel: Int, CaseIterable {
35
+ case low = 1
36
+ case medium = 3
37
+ case high = 5
38
+
39
+ var displayText: String {
40
+ switch self {
41
+ case .low: return "Low"
42
+ case .medium: return "Medium"
43
+ case .high: return "High"
44
+ }
45
+ }
46
+ }
47
+
48
+ enum BasicPIRSensitivityLevel: String, CaseIterable {
49
+ case low = "1"
50
+ case medium = "2"
51
+ case high = "3"
52
+
53
+ var displayText: String {
54
+ switch self {
55
+ case .low: return "Low"
56
+ case .medium: return "Medium"
57
+ case .high: return "High"
58
+ }
59
+ }
60
+ }
61
+
62
+ enum SDCardRecordType: String, CaseIterable {
63
+ case eventRecording = "1"
64
+ case nonStop = "2"
65
+
66
+ var displayText: String {
67
+ switch self {
68
+ case .nonStop: return "Non-Stop"
69
+ case .eventRecording: return "Event Recording"
70
+ }
71
+ }
72
+ }
73
+
74
+ enum ChimeType: String, CaseIterable {
75
+ case none = "0"
76
+ case mechanical = "1"
77
+ case digital = "2"
78
+ case noBells = "3"
79
+
80
+ var displayText: String {
81
+ switch self {
82
+ case .none: return "Not Selected"
83
+ case .mechanical: return "Mechanical"
84
+ case .digital: return "Digital"
85
+ case .noBells: return "No Bells"
86
+ }
87
+ }
88
+ }
89
+
90
+ struct ListStyleModifier: ViewModifier {
91
+ // Removes default background for iOS 16+
92
+ // Applies plain style for iOS below 16
93
+ func body(content: Content) -> some View {
94
+ if #available(iOS 16.0, *) {
95
+ content
96
+ .scrollContentBackground(.hidden)
97
+ } else {
98
+ content
99
+ .listStyle(.plain)
100
+ }
101
+ }
102
+ }
103
+
104
+ struct Settings: View {
105
+ @Binding var isAdvancedSettings: Bool
106
+ @Binding var isStorageSettings: Bool
107
+ @State private var isResetWifiAlertVisible = false
108
+ @State private var isRemoveDoorbellAlertVisible = false
109
+ @State private var isRemoveDoorbellFailureAlertVisible = false
110
+ @ObservedObject var tuya = Tuya.shared
111
+
112
+ private var isRemoveDoorbellButtonVisible: Bool {
113
+ !tuya.isResident || (tuya.displayRemoveDoorbellButton ?? false)
114
+ }
115
+
116
+ var body: some View {
117
+ ZStack {
118
+ List {
119
+ if isAdvancedSettings {
120
+ AdvancedSettings()
121
+ .listRowBackground(LocalColor.Monochrome.white)
122
+ } else if isStorageSettings {
123
+ StorageSettings()
124
+ .listRowBackground(LocalColor.Monochrome.white)
125
+ } else {
126
+ BasicSettingsSection
127
+ .listRowBackground(LocalColor.Monochrome.white)
128
+ MotionDetectionSection
129
+ .listRowBackground(LocalColor.Monochrome.white)
130
+ StorageSettingsSection
131
+ .listRowBackground(LocalColor.Monochrome.white)
132
+ if !SettingsManager.shared.is8s() {
133
+ PowerInformationSection
134
+ .listRowBackground(LocalColor.Monochrome.white)
135
+ }
136
+ if !SettingsManager.shared.isAosu() {
137
+ BellChimeSettingsSection
138
+ .listRowBackground(LocalColor.Monochrome.white)
139
+ }
140
+ AdvancedSettingsSection
141
+ .listRowBackground(LocalColor.Monochrome.white)
142
+
143
+ if isRemoveDoorbellButtonVisible {
144
+ RemoveDoorbellSection
145
+ .listRowBackground(LocalColor.Main.light)
146
+ }
147
+ }
148
+ }
149
+ .modifier(ListStyleModifier())
150
+ .alert(
151
+ isPresented: $isRemoveDoorbellFailureAlertVisible,
152
+ content: {
153
+ getFailureAlert(
154
+ title: "Error in removing doorbell camera."
155
+ )
156
+ })
157
+
158
+ if tuya.settingsLoader {
159
+ ProgressView()
160
+ .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.black))
161
+ }
162
+ }
163
+ }
164
+
165
+ private var BasicSettingsSection: some View {
166
+ Section(header: Label(title: "Basic Settings", s: true, lightGrey: true, bold: true)) {
167
+ if !Tuya.shared.isAosu {
168
+ toggleSwitch(
169
+ id: "flipScreenSwitch",
170
+ title: "Flip Screen",
171
+ description: "Flip the doorbell camera preview screen.",
172
+ isChecked: $tuya.isFlipEnabled,
173
+ dpKey: ThingSmartCameraDPKey.basicFlipDPName
174
+ )
175
+ }
176
+ toggleSwitch(
177
+ id: "timeWaterMarkSwitch",
178
+ title: "Time Watermark",
179
+ description: "Enabling this will display a timestamp on the doorbell camera preview feed.",
180
+ isChecked: $tuya.isWaterMarkEnabled,
181
+ dpKey: ThingSmartCameraDPKey.basicOSDDPName
182
+ )
183
+ if Tuya.shared.isAosu {
184
+ toggleSwitch(
185
+ id: "antiDismantlingSwitch",
186
+ title: "Anti-Dismantling Alarm",
187
+ description: "Enabling this will trigger an alarm sound if the doorbell is forcibly removed from its mounting case.",
188
+ isChecked: $tuya.isAntiDismantlingAlarmEnabled,
189
+ dpKey: ThingSmartCameraDPKey.init(rawValue: "231")
190
+ )
191
+ }
192
+ NightVisionPicker
193
+ }
194
+ }
195
+
196
+ private var NightVisionPicker: some View {
197
+ SettingsPicker(
198
+ title: "IR Night Vision",
199
+ description: "Doorbell camera's night vision settings.",
200
+ dropDownTitle: "Select Night Vision Mode",
201
+ dropDownList: NightVision.allCases.map { $0.displayText },
202
+ selectedOption: .constant(NightVision(rawValue: tuya.nightVisionLevel)?.displayText ?? "")
203
+ ) { selectedText in
204
+ if let selectedEnum = NightVision.allCases.first(where: { $0.displayText == selectedText }) {
205
+ SettingsManager.shared.setDPValue(
206
+ dpKey: ThingSmartCameraDPKey.basicNightvisionDPName,
207
+ value: selectedEnum.rawValue,
208
+ onSuccess: {
209
+ tuya.nightVisionLevel = selectedEnum.rawValue
210
+ },
211
+ onFailure: {
212
+ print("Tuya: Failed to update night mode")
213
+ }
214
+ )
215
+ }
216
+ }
217
+ }
218
+
219
+ private var MotionDetectionSection: some View {
220
+ Section(header: Label(title: "Motion Detection", s: true, lightGrey: true, bold: true)) {
221
+ let is8s = SettingsManager.shared.is8s()
222
+ let isAosu = SettingsManager.shared.isAosu()
223
+
224
+ toggleSwitch(
225
+ id: "motionDetectionSwitch",
226
+ title: "Motion Detection",
227
+ description: "Triggered motion will send push notifications.",
228
+ isChecked: is8s || isAosu ? $tuya.isMotionDetectionEnabled : $tuya.isPIRDetectionEnabled,
229
+ dpKey: is8s || isAosu ? ThingSmartCameraDPKey.motionDetectDPName : ThingSmartCameraDPKey.init(rawValue: "240")
230
+ )
231
+ if isAosu && tuya.isMotionDetectionEnabled {
232
+ BasicPIRSensitivityPicker
233
+ } else if is8s && tuya.isMotionDetectionEnabled {
234
+ MotionSensitivityPicker
235
+ } else if !is8s && tuya.isPIRDetectionEnabled {
236
+ PIRSensitivityPicker
237
+ }
238
+ }
239
+ }
240
+
241
+ private var PIRSensitivityPicker: some View {
242
+ SettingsPicker(
243
+ title: "Motion Sensitivity Level",
244
+ dropDownTitle: "Select Motion Sensitivity Level",
245
+ dropDownList: PIRSensitivityLevel.allCases.map { $0.displayText },
246
+ selectedOption: .constant(PIRSensitivityLevel(rawValue: tuya.pirSensitivityLevel)?.displayText ?? "")
247
+ ) { selectedText in
248
+ if let selectedEnum = PIRSensitivityLevel.allCases.first(where: { $0.displayText == selectedText }) {
249
+ SettingsManager.shared.setDPValue(
250
+ dpKey: ThingSmartCameraDPKey.init(rawValue: "241"),
251
+ value: selectedEnum.rawValue,
252
+ onSuccess: {
253
+ print("Tuya: Successfully updated PIR sensitivity level.")
254
+ tuya.pirSensitivityLevel = selectedEnum.rawValue
255
+ },
256
+ onFailure: {
257
+ print("Tuya: Failed to update PIR sensitivity level.")
258
+ }
259
+ )
260
+ }
261
+ }
262
+ }
263
+
264
+ private var MotionSensitivityPicker: some View {
265
+ SettingsPicker(
266
+ title: "Motion Sensitivity Level",
267
+ dropDownTitle: "Select Motion Sensitivity Level",
268
+ dropDownList: MotionSensitivityLevel.allCases.map { $0.displayText },
269
+ selectedOption: .constant(MotionSensitivityLevel(rawValue: tuya.motionSensitivityLevel)?.displayText ?? "")
270
+ ) { selectedText in
271
+ if let selectedEnum = MotionSensitivityLevel.allCases.first(where: { $0.displayText == selectedText }) {
272
+ SettingsManager.shared.setDPValue(
273
+ dpKey: ThingSmartCameraDPKey.motionSensitivityDPName,
274
+ value: selectedEnum.rawValue,
275
+ onSuccess: {
276
+ print("Tuya: Successfully updated Motion sensitivity level.")
277
+ tuya.motionSensitivityLevel = selectedEnum.rawValue
278
+ },
279
+ onFailure: {
280
+ print("Tuya: Failed to update PIR sensitivity level.")
281
+ }
282
+ )
283
+ }
284
+ }
285
+ }
286
+
287
+ private var BasicPIRSensitivityPicker: some View {
288
+ SettingsPicker(
289
+ title: "Motion Sensitivity Level",
290
+ dropDownTitle: "Select Motion Sensitivity Level",
291
+ dropDownList: BasicPIRSensitivityLevel.allCases.map { $0.displayText },
292
+ selectedOption: .constant(BasicPIRSensitivityLevel(rawValue: tuya.basicPIRSensitivityLevel)?.displayText ?? "")
293
+ ) { selectedText in
294
+ if let selectedEnum = BasicPIRSensitivityLevel.allCases.first(where: { $0.displayText == selectedText }) {
295
+ SettingsManager.shared.setDPValue(
296
+ dpKey: ThingSmartCameraDPKey.basicPIRDPName,
297
+ value: selectedEnum.rawValue,
298
+ onSuccess: {
299
+ print("Tuya: Successfully updated Motion sensitivity level.")
300
+ tuya.basicPIRSensitivityLevel = selectedEnum.rawValue
301
+ },
302
+ onFailure: {
303
+ print("Tuya: Failed to update PIR sensitivity level.")
304
+ }
305
+ )
306
+ }
307
+ }
308
+ }
309
+
310
+ private var StorageSettingsSection: some View {
311
+ Section(header: Label(title: "Storage Settings", s: true, lightGrey: true, bold: true)) {
312
+ HStack {
313
+ VStack(alignment: .leading) {
314
+ Label(
315
+ title: "Storage Settings",
316
+ l: true,
317
+ black: true
318
+ )
319
+
320
+ let description = sdCardStatusDescription(for: tuya.sdCardStatus)
321
+
322
+ if !description.isEmpty {
323
+ Label(
324
+ title: description,
325
+ s: true,
326
+ lightGrey: true,
327
+ left: true
328
+ )
329
+ .padding(.top, 1)
330
+ }
331
+ }
332
+
333
+ Spacer()
334
+
335
+ Label(
336
+ title: sdCardStatusText(for: tuya.sdCardStatus),
337
+ l: true,
338
+ lightGrey: true,
339
+ right: true
340
+ )
341
+
342
+ Image(systemName: "chevron.right")
343
+ .foregroundColor(LocalColor.Primary.secondary)
344
+ }
345
+ .contentShape(Rectangle())
346
+ .onTapGesture { isStorageSettings = true }
347
+
348
+ if SettingsManager.shared.is8s() {
349
+ toggleSwitch(
350
+ id: "sdCardRecordingSwitch",
351
+ title: "SD Card Recording",
352
+ description: nil,
353
+ isChecked: $tuya.isSDCardStorageEnabled,
354
+ dpKey: ThingSmartCameraDPKey.sdCardRecordDPName
355
+ )
356
+
357
+ if tuya.isSDCardStorageEnabled {
358
+ RecordingModePicker
359
+ }
360
+ }
361
+
362
+ HStack {
363
+ Label(
364
+ title: "Reset WiFi",
365
+ l: true,
366
+ black: true
367
+ )
368
+
369
+ Spacer()
370
+
371
+ Image(systemName: "chevron.right")
372
+ .foregroundColor(LocalColor.Primary.secondary)
373
+ }
374
+ .contentShape(Rectangle())
375
+ .onTapGesture { isResetWifiAlertVisible = true }
376
+ .alert(isPresented: $isResetWifiAlertVisible) {
377
+ getAlert(
378
+ title: "",
379
+ message: "Resetting your Wi-Fi will also reset your doorbell. You'll need to set it up again afterward. Do you want to continue?",
380
+ primaryButtonTitle: "Reset Wi-Fi",
381
+ withCancelButton: true,
382
+ secondaryButtonTitle: "Cancel",
383
+ primaryAction: {
384
+ if let cameraType = tuya.cameraType {
385
+ KeylessListener.emitter.resetWifiForDoorbell(
386
+ withDeviceID: cameraType.devId) { success, message in
387
+ if success {
388
+ print("Tuya: Successfully navigated to the 'Add Doorbell' screen.")
389
+ isResetWifiAlertVisible = false
390
+ AppUtility.disconnectAndClose()
391
+ } else {
392
+ print("Tuya: Failed to navigate to the 'Add Doorbell' screen.")
393
+ isResetWifiAlertVisible = false
394
+ }
395
+ }
396
+ }
397
+ }
398
+ )
399
+ }
400
+ }
401
+ }
402
+
403
+ private var RecordingModePicker: some View {
404
+ SettingsPicker(
405
+ title: "Recording Mode",
406
+ description: tuya.sdCardRecordingType == "1" ? "Event will be recorded when motion is detected." : "Event will be recorded continuously.",
407
+ dropDownTitle: "Select Recording Mode",
408
+ dropDownList: SDCardRecordType.allCases.map { $0.displayText },
409
+ selectedOption: .constant(SDCardRecordType(rawValue: tuya.sdCardRecordingType)?.displayText ?? "")
410
+ ) { selectedText in
411
+ if let selectedEnum = SDCardRecordType.allCases.first(where: { $0.displayText == selectedText }) {
412
+ SettingsManager.shared.setDPValue(
413
+ dpKey: ThingSmartCameraDPKey.recordModeDPName,
414
+ value: selectedEnum.rawValue,
415
+ onSuccess: {
416
+ print("Tuya: Successfully updated SD card recording type.")
417
+ tuya.sdCardRecordingType = selectedEnum.rawValue
418
+ },
419
+ onFailure: {
420
+ print("Tuya: Failed to update SD card recording type.")
421
+ }
422
+ )
423
+ }
424
+ }
425
+ }
426
+
427
+ private var PowerInformationSection: some View {
428
+ Section(header: Label(title: "Power Information", s: true, lightGrey: true, bold: true)) {
429
+ HStack {
430
+ Label(
431
+ title: "Power Source",
432
+ l: true,
433
+ black: true
434
+ )
435
+
436
+ Spacer()
437
+
438
+ Label(
439
+ title: tuya.powerMode == "0" ? "Battery (\(tuya.remainingBattery!)%)" : "Charging",
440
+ l: true,
441
+ lightGrey: true,
442
+ right: true
443
+ )
444
+ }
445
+ }
446
+ }
447
+
448
+ private var BellChimeSettingsSection: some View {
449
+ Section(header: Label(title: "Bell/Chime Connection Settings", s: true, lightGrey: true, bold: true)) {
450
+ SettingsPicker(
451
+ title: "Chime Type",
452
+ description: SettingsManager.shared.is8s() ? "Mechanical chime type requires the doorbell to be wired to the home doorbell chime system." : "Mechanical chime type requires the doorbell to be wired to the home doorbell chime system. Digital chime does not require to be wired.",
453
+ dropDownTitle: "Select Chime Type",
454
+ dropDownList: filteredChimeTypes().map { $0.displayText },
455
+ selectedOption: .constant(ChimeType(rawValue: tuya.chimeType)?.displayText ?? "")
456
+ ) { selectedText in
457
+ if let selectedEnum = ChimeType.allCases.first(where: { $0.displayText == selectedText }) {
458
+ SettingsManager.shared.setDPValue(
459
+ dpKey: ThingSmartCameraDPKey.init(rawValue: "165"),
460
+ value: selectedEnum.rawValue,
461
+ onSuccess: {
462
+ print("Tuya: Successfully updated chime type to \(selectedEnum.rawValue)")
463
+ tuya.chimeType = selectedEnum.rawValue
464
+ },
465
+ onFailure: {
466
+ print("Tuya: Failed to update chime type mode")
467
+ }
468
+ )
469
+ }
470
+ }
471
+ }
472
+ }
473
+
474
+ private func filteredChimeTypes() -> [ChimeType] {
475
+ // Digital chime type is not available for 8s model.
476
+ if SettingsManager.shared.is8s() {
477
+ return ChimeType.allCases.filter { $0 != .none && $0 != .digital }
478
+ } else {
479
+ return ChimeType.allCases.filter { $0 != .none }
480
+ }
481
+ }
482
+
483
+ private var AdvancedSettingsSection: some View {
484
+ Section(header: Label(title: "Advanced Settings", s: true, lightGrey: true, bold: true)) {
485
+ HStack {
486
+ Label(
487
+ title: "Device Info",
488
+ l: true,
489
+ black: true
490
+ )
491
+
492
+ Spacer()
493
+
494
+ Image(systemName: "chevron.right")
495
+ .foregroundColor(LocalColor.Primary.secondary)
496
+ }
497
+ .contentShape(Rectangle())
498
+ .onTapGesture { isAdvancedSettings = true }
499
+ }
500
+ }
501
+
502
+ private var RemoveDoorbellSection: some View {
503
+ Section {
504
+ HStack {
505
+ Spacer()
506
+
507
+ CustomButton(
508
+ id: "Remove_Doorbell",
509
+ title: "Remove Doorbell",
510
+ l: true,
511
+ secondary: true,
512
+ textColor: LocalColor.Monochrome.white,
513
+ semiBold: true
514
+ ) {
515
+ isRemoveDoorbellAlertVisible = true
516
+ }
517
+ .frame(width: 210, height: 48)
518
+
519
+ Spacer()
520
+ }
521
+ .alert(
522
+ isPresented: $isRemoveDoorbellAlertVisible,
523
+ content: {
524
+ getAlert(
525
+ title: "Remove Doorbell",
526
+ message: "Are you sure you want to remove the doorbell?",
527
+ primaryButtonTitle: "Remove",
528
+ withCancelButton: true,
529
+ secondaryButtonTitle: "Cancel",
530
+ primaryAction: {
531
+ isRemoveDoorbellAlertVisible = false
532
+ tuya.settingsLoader = true
533
+ if let cameraType = tuya.cameraType {
534
+ KeylessListener.emitter.removeCamera(
535
+ withDeviceID: cameraType.devId) { success, message in
536
+ if success {
537
+ print("Tuya: Remove Doorbell Success")
538
+ tuya.settingsLoader = false
539
+ AppUtility.dismissRootViewController()
540
+ } else {
541
+ print("Tuya: Remove Doorbell Failed")
542
+ tuya.settingsLoader = false
543
+ isRemoveDoorbellFailureAlertVisible = true
544
+ }
545
+ }
546
+ }
547
+ }
548
+ )
549
+ })
550
+ }
551
+ }
552
+
553
+ private func toggleSwitch(
554
+ id: String,
555
+ title: String,
556
+ description: String?,
557
+ isChecked: Binding<Bool>,
558
+ dpKey: ThingSmartCameraDPKey
559
+ ) -> some View {
560
+ Switch(
561
+ id: id,
562
+ checked: isChecked
563
+ ) { value in
564
+ SettingsManager.shared.setDPValue(
565
+ dpKey: dpKey,
566
+ value: value
567
+ )
568
+ } content: {
569
+ VStack(alignment: .leading) {
570
+ Label(
571
+ title: title,
572
+ l: true,
573
+ grey: true,
574
+ left: true
575
+ )
576
+
577
+ if let value = description {
578
+ Label(
579
+ title: value,
580
+ s: true,
581
+ lightGrey: true,
582
+ left: true
583
+ )
584
+ .padding(.top, 1)
585
+ }
586
+ }
587
+ }
588
+ }
589
+
590
+ private func sdCardStatusDescription(for status: Int) -> String {
591
+ switch status {
592
+ case 1: return "Functioning as expected."
593
+ case 2: return "Not functioning as expected. Please check the SD card."
594
+ case 5: return "Check to ensure SD card is inserted."
595
+ default: return ""
596
+ }
597
+ }
598
+
599
+ private func sdCardStatusText(for status: Int) -> String {
600
+ switch status {
601
+ case 1: return "Normal"
602
+ case 2: return "Abnormal"
603
+ case 3: return "Insufficient capacity"
604
+ case 4: return "Formatting…"
605
+ case 5: return "No Storage"
606
+ default: return "Unknown"
607
+ }
608
+ }
609
+ }
610
+
611
+ struct SettingsPicker: View {
612
+
613
+ let title: String
614
+ var description: String? = nil
615
+ let dropDownTitle: String
616
+ let dropDownList: [String]
617
+ @Binding var selectedOption: String
618
+ var onDropDownItemSelected: (String) -> Void
619
+
620
+ @State private var showAlert: Bool = false
621
+
622
+ var body: some View {
623
+ HStack {
624
+ VStack(alignment: .leading) {
625
+ Label(
626
+ title: title,
627
+ l: true,
628
+ grey: true,
629
+ left: true
630
+ )
631
+
632
+ if let description = description {
633
+ Label(
634
+ title: description,
635
+ s: true,
636
+ lightGrey: true,
637
+ left: true,
638
+ maxLines: 5
639
+ )
640
+ .padding(.top, 1)
641
+ }
642
+ }
643
+ .padding(.trailing, 5)
644
+
645
+ Spacer()
646
+
647
+ HStack {
648
+ Label(
649
+ title: selectedOption,
650
+ m: true,
651
+ lightGrey: true,
652
+ left: true,
653
+ maxLines: 2
654
+ )
655
+
656
+ Image(systemName: "chevron.right")
657
+ .foregroundColor(LocalColor.Primary.secondary)
658
+ }
659
+ .padding(.leading, 5)
660
+ }
661
+ .contentShape(Rectangle())
662
+ .onTapGesture { showAlert = true }
663
+ .confirmationDialog(dropDownTitle, isPresented: $showAlert, titleVisibility: .visible) {
664
+ ForEach(dropDownList, id: \.self) { option in
665
+ Button(option) {
666
+ selectedOption = option
667
+ onDropDownItemSelected(option)
668
+ }
669
+ }
670
+ }
671
+ }
672
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file