@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,105 @@
1
+ import SwiftUI
2
+
3
+ struct Label: View {
4
+ var id: String = ""
5
+ var title: String
6
+
7
+ // Font Size Options
8
+ var xs: Bool = false
9
+ var s: Bool = false
10
+ var m: Bool = false
11
+ var l: Bool = false
12
+ var xl18: Bool = false
13
+ var xl20: Bool = false
14
+ var xl22: Bool = false
15
+ var xl24: Bool = false
16
+ var xl26: Bool = false
17
+ var xl28: Bool = false
18
+
19
+ // Color Options
20
+ var primary: Bool = false
21
+ var secondary: Bool = false
22
+ var lightGrey: Bool = false
23
+ var grey: Bool = false
24
+ var white: Bool = false
25
+ var black: Bool = false
26
+ var customColor: Color? = nil
27
+
28
+ // Font Weight Options
29
+ var light: Bool = false
30
+ var medium: Bool = false
31
+ var semiBold: Bool = false
32
+ var bold: Bool = false
33
+
34
+ // Text Alignment Options
35
+ var left: Bool = false
36
+ var right: Bool = false
37
+ var center: Bool = false
38
+
39
+ // Text Decoration
40
+ var underLine: Bool = false
41
+ var strikeThrough: Bool = false
42
+
43
+ var maxLines: Int? = nil
44
+
45
+ var body: some View {
46
+ let textAlign: TextAlignment = {
47
+ if left { return .leading }
48
+ if right { return .trailing }
49
+ if center { return .center }
50
+ return .leading
51
+ }()
52
+
53
+ let color: Color = {
54
+ if let customColor = customColor {
55
+ return customColor
56
+ }
57
+ if primary { return LocalColor.Primary.light }
58
+ if secondary { return LocalColor.Primary.secondary }
59
+ if lightGrey { return LocalColor.Monochrome.regular }
60
+ if grey { return LocalColor.Monochrome.medium }
61
+ if white { return LocalColor.Monochrome.white }
62
+ if black { return LocalColor.Monochrome.black }
63
+ return LocalColor.Primary.light
64
+ }()
65
+
66
+ let font: Font = {
67
+ var fontName: String
68
+ switch (light, medium, semiBold, bold) {
69
+ case (true, _, _, _):
70
+ fontName = LocalFont.FontFamily.light
71
+ case (_, true, _, _):
72
+ fontName = LocalFont.FontFamily.medium
73
+ case (_, _, true, _):
74
+ fontName = LocalFont.FontFamily.semiBold
75
+ case (_, _, _, true):
76
+ fontName = LocalFont.FontFamily.bold
77
+ default:
78
+ fontName = LocalFont.FontFamily.medium
79
+ }
80
+
81
+ let fontSize: CGFloat
82
+ if xs { fontSize = LocalFont.FontSize.XS }
83
+ else if s { fontSize = LocalFont.FontSize.S }
84
+ else if m { fontSize = LocalFont.FontSize.M }
85
+ else if l { fontSize = LocalFont.FontSize.L }
86
+ else if xl18 { fontSize = LocalFont.FontSize.XL18 }
87
+ else if xl20 { fontSize = LocalFont.FontSize.XL20 }
88
+ else if xl22 { fontSize = LocalFont.FontSize.XL22 }
89
+ else if xl24 { fontSize = LocalFont.FontSize.XL24 }
90
+ else if xl26 { fontSize = LocalFont.FontSize.XL26 }
91
+ else if xl28 { fontSize = LocalFont.FontSize.XL28 }
92
+ else { fontSize = LocalFont.FontSize.XL18 }
93
+
94
+ return Font.custom(fontName, size: fontSize)
95
+ }()
96
+
97
+ Text(title)
98
+ .font(font)
99
+ .foregroundColor(color)
100
+ .lineLimit(maxLines)
101
+ .fixedSize(horizontal: false, vertical: true) // Prevents vertical truncation
102
+ .multilineTextAlignment(textAlign)
103
+ .accessibility(identifier: id.isEmpty ? title : id)
104
+ }
105
+ }
@@ -0,0 +1,61 @@
1
+ import SwiftUI
2
+
3
+ struct Switch<Content: View>: View {
4
+ var id: String
5
+ var disabled: Bool = false
6
+ @Binding var checked: Bool
7
+ var onChange: (Bool) -> Void
8
+ let content: () -> Content
9
+
10
+ var body: some View {
11
+ let color = LocalColor.Main.dark
12
+
13
+ HStack {
14
+ Toggle(isOn: Binding(
15
+ get: { checked },
16
+ set: { newValue in
17
+ checked = newValue
18
+ onChange(newValue)
19
+ HeapAnalytics.trackEvent(eventName: id)
20
+ }
21
+ )) {}
22
+ .toggleStyle(SwitchToggleStyle(tint: color, content: content))
23
+ .disabled(disabled)
24
+ .accessibility(identifier: id)
25
+ }
26
+ }
27
+ }
28
+
29
+ struct SwitchToggleStyle<Content: View>: ToggleStyle {
30
+ var tint: Color
31
+ let content: () -> Content
32
+
33
+ func makeBody(configuration: Configuration) -> some View {
34
+ HStack {
35
+ content()
36
+ Spacer()
37
+
38
+ HStack {
39
+ Rectangle()
40
+ .fill(configuration.isOn ? tint : Color.gray)
41
+ .frame(width: 51, height: 31)
42
+ .cornerRadius(16)
43
+ .overlay(
44
+ Circle()
45
+ .fill(Color.white)
46
+ .shadow(radius: 1)
47
+ .padding(3)
48
+ .offset(x: configuration.isOn ? 10 : -10)
49
+ .animation(.easeInOut(duration: 0.2), value: configuration.isOn)
50
+ .gesture(
51
+ DragGesture(minimumDistance: 0)
52
+ .onEnded { _ in
53
+ configuration.isOn.toggle()
54
+ }
55
+ )
56
+ )
57
+ .padding(.leading, 10)
58
+ }
59
+ }
60
+ }
61
+ }
@@ -0,0 +1,127 @@
1
+ import SwiftUI
2
+
3
+ struct AdvancedSettings: View {
4
+ @ObservedObject var tuya = Tuya.shared
5
+
6
+ var body: some View {
7
+ Section {
8
+ if let cameraType = tuya.cameraType {
9
+ Item(title: "Product Name", value: tuya.tuyaProductName, isAdvancedSetting: true)
10
+ Item(title: "Product ID", value: tuya.tuyaProductID, isAdvancedSetting: true)
11
+ Item(title: "Device ID", value: cameraType.devId, isAdvancedSetting: true)
12
+ Item(title: "Device UUID", value: tuya.uuid, isAdvancedSetting: true)
13
+ Item(title: "Serial Number", value: tuya.serialNumber, isAdvancedSetting: true)
14
+ Item(title: "Firmware Version", value: tuya.firwareVersion, isAdvancedSetting: true)
15
+ }
16
+ }
17
+ .onAppear {
18
+ SettingsManager.shared.getFirmwareVersion()
19
+ }
20
+ }
21
+ }
22
+
23
+ struct StorageSettings: View {
24
+
25
+ @ObservedObject var tuya = Tuya.shared
26
+ @State private var isFormatDoorbellAlertVisible = false
27
+
28
+ var body: some View {
29
+ Section {
30
+ Item(title: "Total Capacity", value: "\(String(format: "%.1f", tuya.totalCapacity))G")
31
+ Item(title: "Used", value: "\(String(format: "%.1f", tuya.used))G")
32
+ Item(title: "Remaining Capacity", value: "\(String(format: "%.1f", tuya.remainingCapacity))G")
33
+ }
34
+ .onAppear {
35
+ SettingsManager.shared.getMemoryCardCapacity()
36
+ }
37
+ .onChange(of: tuya.sdCardStatus) { status in
38
+ SettingsManager.shared.getMemoryCardCapacity()
39
+ }
40
+ .alert(isPresented: $isFormatDoorbellAlertVisible) {
41
+ getAlert(
42
+ title: "Format SD Card?",
43
+ message: "Formatting the SD Card will erase all your saved videos.",
44
+ primaryButtonTitle: "YES",
45
+ withCancelButton: true,
46
+ secondaryButtonTitle: "NO",
47
+ primaryAction: {
48
+ SettingsManager.shared.formatSDCard()
49
+ }
50
+ )
51
+ }
52
+
53
+ Section {
54
+ HStack {
55
+ Spacer()
56
+ CustomButton(
57
+ id: "FormatSDCard",
58
+ title: "Format",
59
+ secondary: true,
60
+ textColor: LocalColor.Monochrome.white,
61
+ semiBold: true,
62
+ disabled: tuya.sdCardStatus == 4
63
+ ) {
64
+ isFormatDoorbellAlertVisible = true
65
+ }
66
+ .frame(width: 150, height: 30)
67
+ .padding(.vertical, 5)
68
+ Spacer()
69
+ }
70
+ }
71
+ .listRowBackground(LocalColor.Main.light)
72
+ }
73
+ }
74
+
75
+ struct Item: View {
76
+ var title: String
77
+ var value: String?
78
+ var isAdvancedSetting: Bool = false
79
+ var background: Color = LocalColor.Monochrome.white
80
+ @State var copySuccess = false
81
+
82
+ var body: some View {
83
+ if let value = value {
84
+ HStack {
85
+ Label(
86
+ id: title,
87
+ title: title,
88
+ l: true,
89
+ black: true,
90
+ semiBold: true
91
+ )
92
+ Spacer()
93
+ Label(
94
+ id: value,
95
+ title: value,
96
+ l: true,
97
+ black: true,
98
+ medium: true,
99
+ right: true,
100
+ maxLines: 3
101
+ )
102
+ .frame(width: UIScreen.main.bounds.width / 2, alignment: .trailing)
103
+ }
104
+ .background(background)
105
+ .onLongPressGesture {
106
+ if (isAdvancedSetting) {
107
+ copyToClipboard(value: value)
108
+ }
109
+ }
110
+ .alert(
111
+ isPresented: $copySuccess,
112
+ content: {
113
+ Alert(
114
+ title: Text(""),
115
+ message: Text("Text copied to clipboard").bold(),
116
+ dismissButton: .default(Text("OK"))
117
+ )
118
+ })
119
+ }
120
+ }
121
+
122
+ private func copyToClipboard(value: String) {
123
+ UIPasteboard.general.string = value
124
+ copySuccess = true
125
+ }
126
+ }
127
+
@@ -0,0 +1,354 @@
1
+ import SwiftUI
2
+
3
+ struct Dashboard: View {
4
+
5
+ @ObservedObject var tuya = Tuya.shared
6
+ @Binding var currentScreen: ScreenState
7
+ @State private var isDoorbellControlVisible = true
8
+ @State private var isPermissionDisclaimerAlertVisible = false
9
+ @EnvironmentObject var orientationManager: OrientationManager
10
+
11
+ var body: some View {
12
+ VStack(spacing: 0) {
13
+ ZStack(alignment: .bottom) {
14
+ Preview(isDoorbellControlVisible: $isDoorbellControlVisible)
15
+ .alert(
16
+ isPresented: $tuya.isScreenshotSuccess,
17
+ content: {
18
+ getSuccessAlert(
19
+ title: "A screenshot has been saved to your photo gallery."
20
+ )
21
+ })
22
+
23
+ if tuya.isConnected {
24
+ DoorbellControls(
25
+ isDoorbellControlVisible: $isDoorbellControlVisible,
26
+ isPermissionDisclaimerAlertVisible: $isPermissionDisclaimerAlertVisible
27
+ )
28
+ .padding(.bottom, 10)
29
+ .alert(
30
+ isPresented: $tuya.isRecordingSuccess,
31
+ content: {
32
+ getSuccessAlert(
33
+ title: "A recording has been saved to your photo gallery."
34
+ )
35
+ })
36
+ }
37
+ }
38
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
39
+
40
+ BottomBar(currentScreen: $currentScreen)
41
+ .alert(
42
+ isPresented: $tuya.isRecordingFailure,
43
+ content: {
44
+ getFailureAlert(
45
+ title: "Failed to save the recording to your photo gallery."
46
+ )
47
+ })
48
+ }
49
+ .background(LocalColor.Monochrome.black)
50
+ .onAppear(perform: handleOnAppear)
51
+ .onChange(of: orientationManager.isLandscape) { _ in handleOrientation() }
52
+ .onChange(of: isDoorbellControlVisible) { _ in handleOrientation() }
53
+
54
+ if tuya.dashboardLoader {
55
+ ProgressView()
56
+ .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.white))
57
+ }
58
+
59
+ if tuya.previewLoader {
60
+ ProgressView()
61
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
62
+ .background(LocalColor.Monochrome.black.opacity(0.1))
63
+ .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.white))
64
+ }
65
+ }
66
+
67
+ private func handleOrientation() {
68
+ if orientationManager.isLandscape && isDoorbellControlVisible {
69
+ DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
70
+ isDoorbellControlVisible = false
71
+ }
72
+ }
73
+
74
+ if !orientationManager.isLandscape {
75
+ isDoorbellControlVisible = true
76
+ }
77
+ }
78
+
79
+ private func handleOnAppear() {
80
+ guard tuya.device != nil else { return }
81
+
82
+ if tuya.isPlaybacking {
83
+ tuya.stopPlayback()
84
+ tuya.enableMute(enable: true, type: .playback)
85
+ }
86
+
87
+ if !tuya.isConnected {
88
+ tuya.connect()
89
+ } else if !tuya.isPreviewing {
90
+ tuya.startPreview()
91
+ }
92
+
93
+ if tuya.isConnected {
94
+ tuya.enableMute(enable: false, type: .preview)
95
+ }
96
+
97
+ orientationManager.updateOrientationFlag()
98
+ }
99
+ }
100
+
101
+ struct Preview: View {
102
+
103
+ @ObservedObject var tuya = Tuya.shared
104
+ @Binding var isDoorbellControlVisible: Bool
105
+ @EnvironmentObject var orientationManager: OrientationManager
106
+
107
+ var body: some View {
108
+ ZStack {
109
+ if tuya.previewLoader {
110
+ EmptyView()
111
+ } else if tuya.isConnected && tuya.isPreviewing {
112
+ PreviewView()
113
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
114
+ .onTapGesture {
115
+ isDoorbellControlVisible = true
116
+ }
117
+ } else {
118
+ OfflineScreen()
119
+ }
120
+ }
121
+ .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
122
+ }
123
+ }
124
+
125
+ struct DoorbellControls: View {
126
+
127
+ @ObservedObject var tuya = Tuya.shared
128
+ @Binding var isDoorbellControlVisible: Bool
129
+ @Binding var isPermissionDisclaimerAlertVisible: Bool
130
+ @EnvironmentObject var orientationManager: OrientationManager
131
+
132
+ private var batteryIcon: String {
133
+ if tuya.powerMode == "0" {
134
+ if let remainingBattery = tuya.remainingBattery {
135
+ switch remainingBattery {
136
+ case 91...:
137
+ return "battery_full"
138
+ case 75...90:
139
+ return "battery_good"
140
+ case 40...74:
141
+ return "battery_average"
142
+ default:
143
+ return "battery_low"
144
+ }
145
+ } else {
146
+ return "battery_low"
147
+ }
148
+ } else {
149
+ return "Charging"
150
+ }
151
+ }
152
+
153
+ var body: some View {
154
+ if !orientationManager.isLandscape || isDoorbellControlVisible {
155
+ VStack {
156
+ if !SettingsManager.shared.is8s() {
157
+ HStack {
158
+ Image(imageName: batteryIcon)
159
+ .resizable()
160
+ .aspectRatio(contentMode: .fit)
161
+ .frame(width: 24, height: 24)
162
+
163
+ Label(
164
+ id: "batteryPercentage",
165
+ title: tuya.powerMode == "0" ? "\(tuya.remainingBattery ?? 0)%" : "Charging",
166
+ s: true,
167
+ white: true
168
+ )
169
+ .padding(.leading, 2)
170
+
171
+ Spacer()
172
+ }
173
+ .frame(maxWidth: .infinity)
174
+ .padding(.horizontal, 30)
175
+ }
176
+
177
+ ZStack {
178
+ HStack {
179
+ CustomButton(
180
+ id: "Toggle to \(tuya.isMicOn ? "Tap to mute" : "Tap to speak")",
181
+ title: tuya.isMicOn ? "Tap to mute" : "Tap to speak",
182
+ l: true,
183
+ tertiary: !tuya.isMicOn,
184
+ textColor: LocalColor.Monochrome.white,
185
+ medium: tuya.isMicOn,
186
+ semiBold: true,
187
+ cornerRadius: 40,
188
+ disabled: tuya.previewLoader || !tuya.isConnected || tuya.dashboardLoader
189
+ ) {
190
+ if tuya.isMicOn {
191
+ tuya.stopTalk()
192
+ } else {
193
+ // The speaker needs to be un muted when the mic is turned on.
194
+ if tuya.isMuted {
195
+ tuya.enableMute(enable: false, type: .preview)
196
+ }
197
+ tuya.startTalk()
198
+ }
199
+ }
200
+ .frame(width: 185, height: 70)
201
+ }
202
+ .frame(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
203
+
204
+ HStack {
205
+ Spacer()
206
+
207
+ IconButton(
208
+ imageName: tuya.isHD ? "ty_camera_control_hd_normal" : "ty_camera_control_sd_normal",
209
+ event: tuya.isHD ? "Toggle to SD" : "Toggle to HD",
210
+ size: 35
211
+ ) {
212
+ if tuya.previewLoader || !tuya.isConnected || tuya.dashboardLoader {
213
+ print("Tuya: Toggle Resolution is disabled")
214
+ } else {
215
+ tuya.changeResolution(resolution: tuya.isHD ? .standard : .high)
216
+ }
217
+ }
218
+ .padding(.trailing, 90)
219
+
220
+ Spacer()
221
+
222
+ IconButton(
223
+ imageName: orientationManager.isLandscape ? "exit_fullscreen" : "fullscreen",
224
+ event: orientationManager.isLandscape ? "Exit Full Screen" : "Enter Full Screen",
225
+ size: 30
226
+ ) {
227
+ orientationManager.toggleOrientation()
228
+ }
229
+ .padding(.leading, 90)
230
+
231
+ Spacer()
232
+ }
233
+ }
234
+ .frame(maxWidth: /*@START_MENU_TOKEN@*/.infinity/*@END_MENU_TOKEN@*/)
235
+ }
236
+ }
237
+ }
238
+ }
239
+
240
+ struct BottomBar: View {
241
+
242
+ @ObservedObject var tuya = Tuya.shared
243
+ @Binding var currentScreen: ScreenState
244
+ @EnvironmentObject var orientationManager: OrientationManager
245
+
246
+ var body: some View {
247
+ if !orientationManager.isLandscape {
248
+ HStack {
249
+ Spacer()
250
+
251
+ IconButton(
252
+ imageName: tuya.isMuted ? "keyless_sound_off" : "keyless_sound_on",
253
+ event: tuya.isMuted ? "Speaker On" : "Speaker Off",
254
+ size: tuya.isMuted ? 28 : 40,
255
+ action: {
256
+ guard tuya.isConnected else {
257
+ print("Camera not connected. Speaker action disabled.")
258
+ return
259
+ }
260
+ tuya.enableMute(enable: !tuya.isMuted, type: .preview)
261
+ }
262
+ )
263
+
264
+ Spacer()
265
+
266
+ IconButton(
267
+ imageName: "keyless_photo",
268
+ event: "Screenshot",
269
+ size: 25,
270
+ action: {
271
+ guard tuya.isConnected else {
272
+ print("Camera not connected. Screenshot action disabled.")
273
+ return
274
+ }
275
+ tuya.screenshot()
276
+ }
277
+ )
278
+
279
+ Spacer()
280
+
281
+ IconButton(
282
+ imageName: tuya.isRecording ? "keyless_record_on" : "keyless_record",
283
+ event: tuya.isRecording ? "Stop Recording" : "Start Recording",
284
+ size: tuya.isRecording ? 40 : 28,
285
+ action: {
286
+ guard tuya.isConnected else {
287
+ print("Camera not connected. Recording action disabled.")
288
+ return
289
+ }
290
+ if tuya.isRecording {
291
+ tuya.stopRecording()
292
+ } else {
293
+ tuya.startRecording()
294
+ }
295
+ }
296
+ )
297
+
298
+ Spacer()
299
+
300
+ IconButton(
301
+ imageName: "keyless_play_list",
302
+ event: "Playback",
303
+ size: 25,
304
+ action: {
305
+ if tuya.isRecording {
306
+ tuya.stopRecording()
307
+ } else {
308
+ currentScreen = .playback
309
+ }
310
+ }
311
+ )
312
+
313
+ Spacer()
314
+
315
+ IconButton(
316
+ imageName: "keyless_message",
317
+ event: "Messages",
318
+ size: 25,
319
+ action: { currentScreen = .messages }
320
+ )
321
+
322
+ Spacer()
323
+ }
324
+ .padding(.top)
325
+ .padding(.horizontal)
326
+ .frame(height: 70)
327
+ .padding(.bottom, 15)
328
+ .background(LocalColor.Monochrome.grey)
329
+ .edgesIgnoringSafeArea(.horizontal)
330
+ }
331
+ }
332
+ }
333
+
334
+ struct IconButton: View {
335
+ let imageName: String
336
+ let event: String
337
+ let size: CGFloat
338
+ let action: () -> Void
339
+
340
+ var body: some View {
341
+ Button(
342
+ action: {
343
+ action()
344
+ HeapAnalytics.trackEvent(eventName: "Bottom Bar: \(event)")
345
+ }
346
+ ) {
347
+ Image(imageName: imageName)
348
+ .resizable()
349
+ .aspectRatio(contentMode: .fit)
350
+ .frame(width: size, height: size)
351
+ }
352
+ .frame(width: 60)
353
+ }
354
+ }