@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,54 @@
1
+ import Foundation
2
+ import SwiftUI
3
+
4
+ func getAlert(
5
+ title: String,
6
+ message: String,
7
+ primaryButtonTitle: String,
8
+ withCancelButton: Bool = false,
9
+ secondaryButtonTitle: String,
10
+ primaryAction: @escaping () -> Void,
11
+ secondaryAction: @escaping () -> Void = {}
12
+ ) -> Alert {
13
+
14
+ updateAlertBackgroundColor()
15
+
16
+ return Alert(
17
+ title: Text(title),
18
+ message: Text(message),
19
+ primaryButton: withCancelButton
20
+ ? .default(Text(secondaryButtonTitle))
21
+ : .default(Text(secondaryButtonTitle), action: {
22
+ HeapAnalytics.trackEvent(eventName: "\(title)_\(secondaryButtonTitle)")
23
+ secondaryAction()
24
+ }),
25
+ secondaryButton: .default(Text(primaryButtonTitle), action: {
26
+ HeapAnalytics.trackEvent(eventName: "\(title)_\(primaryButtonTitle)")
27
+ primaryAction()
28
+ })
29
+ )
30
+ }
31
+
32
+ func getSuccessAlert(title: String) -> Alert {
33
+
34
+ updateAlertBackgroundColor()
35
+
36
+ return Alert(
37
+ title: Text("Success"),
38
+ message: Text(title),
39
+ dismissButton: .default(Text("OK"))
40
+ )
41
+ }
42
+
43
+ func getFailureAlert(title: String) -> Alert {
44
+
45
+ updateAlertBackgroundColor()
46
+
47
+ return Alert(
48
+ title: Text("Failed"),
49
+ message: Text(title),
50
+ dismissButton: .default(Text("OK"))
51
+ )
52
+ }
53
+
54
+
@@ -0,0 +1,100 @@
1
+ import SwiftUI
2
+
3
+ struct AnchorButton: View {
4
+ var id: String
5
+ var title: String
6
+
7
+ // Font Size
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 xl28: Bool = false
17
+
18
+ // Text Color
19
+ var primary: Bool = false
20
+ var secondary: Bool = false
21
+ var black: Bool = false
22
+
23
+ // Font Weight
24
+ var light: Bool = false
25
+ var medium: Bool = false
26
+ var semiBold: Bool = false
27
+ var bold: Bool = false
28
+
29
+ // Text Alignment
30
+ var left: Bool = false
31
+ var right: Bool = false
32
+ var center: Bool = true
33
+
34
+ var underLine: Bool = false
35
+ var strikeThrough: Bool = false
36
+ var disabled: Bool = false
37
+ var onClick: () -> Void = {}
38
+
39
+ var body: some View {
40
+ Button(action: {
41
+ if !disabled {
42
+ HeapAnalytics.trackEvent(eventName: id)
43
+ onClick()
44
+ }
45
+ }) {
46
+ Text(title)
47
+ .font(getFont())
48
+ .foregroundColor(getColor())
49
+ .underline(underLine, color: getColor())
50
+ .strikethrough(strikeThrough, color: getColor())
51
+ .frame(maxWidth: .infinity, alignment: getAlignment())
52
+ }
53
+ .disabled(disabled)
54
+ .accessibility(identifier: id)
55
+ }
56
+
57
+ private func getColor() -> Color {
58
+ if primary { return LocalColor.Primary.light }
59
+ if secondary { return LocalColor.Main.dark }
60
+ if black { return LocalColor.Monochrome.black }
61
+ return LocalColor.Primary.light
62
+ }
63
+
64
+ private func getFont() -> Font {
65
+ var fontName: String
66
+ switch (light, medium, semiBold, bold) {
67
+ case (true, _, _, _):
68
+ fontName = LocalFont.FontFamily.light
69
+ case (_, true, _, _):
70
+ fontName = LocalFont.FontFamily.medium
71
+ case (_, _, true, _):
72
+ fontName = LocalFont.FontFamily.semiBold
73
+ case (_, _, _, true):
74
+ fontName = LocalFont.FontFamily.bold
75
+ default:
76
+ fontName = LocalFont.FontFamily.medium
77
+ }
78
+
79
+ let fontSize: CGFloat
80
+ if xs { fontSize = LocalFont.FontSize.XS }
81
+ else if s { fontSize = LocalFont.FontSize.S }
82
+ else if m { fontSize = LocalFont.FontSize.M }
83
+ else if l { fontSize = LocalFont.FontSize.L }
84
+ else if xl18 { fontSize = LocalFont.FontSize.XL18 }
85
+ else if xl20 { fontSize = LocalFont.FontSize.XL20 }
86
+ else if xl22 { fontSize = LocalFont.FontSize.XL22 }
87
+ else if xl24 { fontSize = LocalFont.FontSize.XL24 }
88
+ else if xl28 { fontSize = LocalFont.FontSize.XL28 }
89
+ else { fontSize = LocalFont.FontSize.XL18 }
90
+
91
+ return Font.custom(fontName, size: fontSize)
92
+ }
93
+
94
+ private func getAlignment() -> Alignment {
95
+ if left { return .leading }
96
+ if right { return .trailing }
97
+ if center { return .center }
98
+ return .center // Default to center
99
+ }
100
+ }
@@ -0,0 +1,118 @@
1
+ import SwiftUI
2
+
3
+ struct CustomButton: View {
4
+ var id: String
5
+ var title: String
6
+
7
+ // Font Size
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
+
17
+ // Button Color
18
+ var primary: Bool = false
19
+ var secondary: Bool = false
20
+ var tertiary: Bool = false
21
+ var black: Bool = false
22
+
23
+ // Text/Border Color
24
+ var textColor: Color = .black
25
+ var borderColor: Color? = nil
26
+
27
+ // Font Weight
28
+ var light: Bool = false
29
+ var medium: Bool = false
30
+ var semiBold: Bool = false
31
+ var bold: Bool = false
32
+
33
+ var cornerRadius: CGFloat = 30
34
+ var disabled: Bool = false
35
+ var elevation: Bool = false
36
+ // Icon
37
+ var icon: Image? = nil
38
+
39
+ var onClick: () -> Void = {}
40
+
41
+ var buttonColor: Color {
42
+ if primary {
43
+ return LocalColor.Primary.medium
44
+ } else if secondary {
45
+ return Color(red: 0.953, green: 0.467, blue: 0.529)
46
+ } else if tertiary {
47
+ return LocalColor.Monochrome.regular
48
+ } else if black {
49
+ return LocalColor.Monochrome.black
50
+ } else {
51
+ return LocalColor.Primary.light
52
+ }
53
+ }
54
+
55
+ var body: some View {
56
+
57
+ let font: Font = {
58
+ var fontName: String
59
+ switch (light, medium, semiBold, bold) {
60
+ case (true, _, _, _):
61
+ fontName = LocalFont.FontFamily.light
62
+ case (_, true, _, _):
63
+ fontName = LocalFont.FontFamily.medium
64
+ case (_, _, true, _):
65
+ fontName = LocalFont.FontFamily.semiBold
66
+ case (_, _, _, true):
67
+ fontName = LocalFont.FontFamily.bold
68
+ default:
69
+ fontName = LocalFont.FontFamily.medium
70
+ }
71
+
72
+ let fontSize: CGFloat
73
+ if xs { fontSize = LocalFont.FontSize.XS }
74
+ else if s { fontSize = LocalFont.FontSize.S }
75
+ else if m { fontSize = LocalFont.FontSize.M }
76
+ else if l { fontSize = LocalFont.FontSize.L }
77
+ else if xl18 { fontSize = LocalFont.FontSize.XL18 }
78
+ else if xl20 { fontSize = LocalFont.FontSize.XL20 }
79
+ else if xl22 { fontSize = LocalFont.FontSize.XL22 }
80
+ else if xl24 { fontSize = LocalFont.FontSize.XL24 }
81
+ else { fontSize = LocalFont.FontSize.M }
82
+
83
+ return Font.custom(fontName, size: fontSize)
84
+ }()
85
+
86
+ HStack() {
87
+ if let icon = icon {
88
+ icon
89
+ .resizable()
90
+ .aspectRatio(contentMode: .fit)
91
+ .frame(width: 24, height: 24)
92
+ }
93
+
94
+ Text(title)
95
+ .font(font)
96
+ .foregroundColor(textColor)
97
+ .frame(maxWidth: .infinity)
98
+ }
99
+ .padding()
100
+ .background(buttonColor)
101
+ .opacity(disabled ? 0.5 : 1)
102
+ .cornerRadius(cornerRadius)
103
+ .overlay(
104
+ RoundedRectangle(cornerRadius: cornerRadius)
105
+ .stroke(borderColor ?? Color.clear, lineWidth: borderColor != nil ? 1 : 0)
106
+ )
107
+ .shadow(color: elevation ? .gray.opacity(0.5) : .clear, radius: elevation ? 5 : 0)
108
+ .onTapGesture {
109
+ if !disabled {
110
+ HeapAnalytics.trackEvent(eventName: id)
111
+ onClick()
112
+ }
113
+ }
114
+ .disabled(disabled)
115
+ .accessibility(identifier: "\(id)Button")
116
+ }
117
+ }
118
+
@@ -0,0 +1,275 @@
1
+ import SwiftUI
2
+
3
+ struct CustomDatePicker: View {
4
+
5
+ @Binding var isVisible: Bool
6
+ @Binding var selectedDate: Date
7
+ var availableDays: [Int]
8
+ var minDate: Date? = nil
9
+ var onDateSelected: (Date) -> Void
10
+ var onMonthChanged: (Date) -> Void
11
+ var onCancel: () -> Void
12
+ var onOk: () -> Void
13
+ var onAppear: () -> Void
14
+
15
+ @State private var tempDate: Date = Date()
16
+ @State private var displayedDate: Date = Date()
17
+
18
+ @ObservedObject var tuya = Tuya.shared
19
+
20
+ var body: some View {
21
+ if isVisible {
22
+ ZStack {
23
+ LocalColor.Monochrome.black.opacity(0.5)
24
+ .edgesIgnoringSafeArea(.all)
25
+ .onTapGesture {
26
+ isVisible = false
27
+ }
28
+
29
+ VStack(spacing: 0) {
30
+ HStack {
31
+ VStack {
32
+ Label(
33
+ title: "Select a Date",
34
+ l: true,
35
+ white: true,
36
+ left: true
37
+ )
38
+ .frame(maxWidth: .infinity, alignment: .leading)
39
+ .padding(.top)
40
+
41
+ Label(
42
+ title: formatDate(date: tempDate),
43
+ xl26: true,
44
+ white: true,
45
+ left: true
46
+ )
47
+ .frame(maxWidth: .infinity, alignment: .leading)
48
+ .padding(.vertical, 6)
49
+ }
50
+ .padding(.horizontal, 12)
51
+
52
+ Spacer()
53
+ }
54
+ .frame(maxWidth: .infinity)
55
+ .background(LocalColor.Main.dark)
56
+
57
+ HStack {
58
+ Button(action: {
59
+ displayedDate = previousMonth(from: displayedDate)
60
+ onMonthChanged(displayedDate)
61
+ }) {
62
+ Image(systemName: "chevron.left")
63
+ .padding()
64
+ .foregroundColor(LocalColor.Main.dark)
65
+ }
66
+ .disabled(tuya.datePickerLoader)
67
+
68
+ Spacer()
69
+
70
+ Label(
71
+ title: formatMonthYear(date: displayedDate),
72
+ xl18: true,
73
+ black: true,
74
+ bold: true
75
+ )
76
+
77
+ Spacer()
78
+
79
+ Button(action: {
80
+ displayedDate = nextMonth(from: displayedDate)
81
+ onMonthChanged(displayedDate)
82
+ }) {
83
+ Image(systemName: "chevron.right")
84
+ .padding()
85
+ .foregroundColor(LocalColor.Main.dark)
86
+ }
87
+ .disabled(tuya.datePickerLoader)
88
+ }
89
+ .padding()
90
+ .background(LocalColor.Monochrome.white)
91
+
92
+ if tuya.datePickerLoader {
93
+ VStack {
94
+ Spacer()
95
+ ProgressView()
96
+ .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.black))
97
+ Spacer()
98
+ }
99
+ .frame(maxWidth: .infinity)
100
+ .frame(height: 240)
101
+ } else {
102
+ CalendarView(
103
+ displayedDate: displayedDate,
104
+ selectedDate: $tempDate,
105
+ availableDays: availableDays,
106
+ minDate: minDate,
107
+ onDateSelected: { date in
108
+ tempDate = date
109
+ onDateSelected(date)
110
+ }
111
+ )
112
+ .frame(height: 240)
113
+ }
114
+
115
+ HStack {
116
+ AnchorButton(
117
+ id: "DatePicker_Cancel",
118
+ title: "Cancel",
119
+ l: true,
120
+ secondary: true,
121
+ center: true
122
+ ) {
123
+ onCancel()
124
+ }
125
+
126
+ AnchorButton(
127
+ id: "DatePicker_OK",
128
+ title: "OK",
129
+ l: true,
130
+ secondary: true,
131
+ center: true
132
+ ) {
133
+ selectedDate = tempDate
134
+ onOk()
135
+ }
136
+ }
137
+ .padding()
138
+ .padding(.vertical, 6)
139
+ }
140
+ .frame(maxWidth: 320)
141
+ .background(LocalColor.Monochrome.white)
142
+ .cornerRadius(12)
143
+ .shadow(radius: 5)
144
+ .padding(.horizontal, 24)
145
+ }
146
+ .onAppear {
147
+ tempDate = selectedDate
148
+ displayedDate = selectedDate
149
+ onAppear()
150
+ }
151
+ }
152
+ }
153
+
154
+ private func formatDate(date: Date) -> String {
155
+ let formatter = DateFormatter()
156
+ formatter.dateFormat = "MMM dd yyyy"
157
+ return formatter.string(from: date)
158
+ }
159
+
160
+ private func formatMonthYear(date: Date) -> String {
161
+ let formatter = DateFormatter()
162
+ formatter.dateFormat = "MMMM yyyy"
163
+ return formatter.string(from: date)
164
+ }
165
+
166
+ private func previousMonth(from date: Date) -> Date {
167
+ return Calendar.current.date(byAdding: .month, value: -1, to: date)!
168
+ }
169
+
170
+ private func nextMonth(from date: Date) -> Date {
171
+ return Calendar.current.date(byAdding: .month, value: 1, to: date)!
172
+ }
173
+ }
174
+
175
+ struct CalendarView: View {
176
+ let displayedDate: Date
177
+ @Binding var selectedDate: Date
178
+ let availableDays: [Int]
179
+ let minDate: Date?
180
+ var onDateSelected: (Date) -> Void
181
+
182
+ private let daysInWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
183
+
184
+ var body: some View {
185
+ VStack(spacing: 5) {
186
+ HStack {
187
+ ForEach(daysInWeek, id: \.self) { day in
188
+ Label(
189
+ title: day,
190
+ s: true,
191
+ lightGrey: true
192
+ )
193
+ .frame(maxWidth: .infinity)
194
+ }
195
+ }
196
+
197
+ let calendarDays = generateCalendarDays()
198
+ LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 7), spacing: 10) {
199
+ ForEach(calendarDays.indices, id: \.self) { index in
200
+ if let day = calendarDays[index] {
201
+ let isAvailable = isDayAvailable(day)
202
+ let isSelected = isSelectedDate(day)
203
+
204
+ Text("\(day)")
205
+ .font(.footnote)
206
+ .frame(width: 30, height: 30)
207
+ .background(isSelected ? LocalColor.Main.dark : LocalColor.Monochrome.transparent)
208
+ .foregroundColor(isSelected ? LocalColor.Monochrome.white : (isAvailable ? LocalColor.Monochrome.black : LocalColor.Monochrome.regular))
209
+ .overlay(
210
+ Circle()
211
+ .stroke(isAvailable ? LocalColor.Main.dark : LocalColor.Monochrome.transparent, lineWidth: 1)
212
+ )
213
+ .clipShape(Circle())
214
+ .onTapGesture {
215
+ if isAvailable {
216
+ selectDate(day)
217
+ }
218
+ }
219
+ } else {
220
+ Spacer()
221
+ }
222
+ }
223
+ }
224
+ }
225
+ .padding()
226
+ }
227
+
228
+ private func generateCalendarDays() -> [Int?] {
229
+ let calendar = Calendar.current
230
+ let components = calendar.dateComponents([.year, .month], from: displayedDate)
231
+ guard let firstDayOfMonth = calendar.date(from: components) else { return [] }
232
+
233
+ let range = calendar.range(of: .day, in: .month, for: firstDayOfMonth)!
234
+ let firstWeekday = calendar.component(.weekday, from: firstDayOfMonth) - 1
235
+
236
+ var days: [Int?] = Array(repeating: nil, count: firstWeekday)
237
+ days.append(contentsOf: range.map { $0 })
238
+ return days
239
+ }
240
+
241
+ private func isDayAvailable(_ day: Int) -> Bool {
242
+ let calendar = Calendar.current
243
+ let components = DateComponents(year: calendar.component(.year, from: displayedDate),
244
+ month: calendar.component(.month, from: displayedDate),
245
+ day: day)
246
+ let date = calendar.date(from: components)!
247
+ if let minDate = minDate {
248
+ return availableDays.contains(day) && date >= minDate
249
+ }
250
+ return availableDays.contains(day)
251
+ }
252
+
253
+ private func isSelectedDate(_ day: Int) -> Bool {
254
+ let calendar = Calendar.current
255
+ let selectedDay = calendar.component(.day, from: selectedDate)
256
+ let selectedMonth = calendar.component(.month, from: selectedDate)
257
+ let selectedYear = calendar.component(.year, from: selectedDate)
258
+
259
+ let displayedMonth = calendar.component(.month, from: displayedDate)
260
+ let displayedYear = calendar.component(.year, from: displayedDate)
261
+
262
+ return day == selectedDay && selectedMonth == displayedMonth && selectedYear == displayedYear
263
+ }
264
+
265
+ private func selectDate(_ day: Int) {
266
+ let calendar = Calendar.current
267
+ var components = calendar.dateComponents([.year, .month], from: displayedDate)
268
+ components.day = day
269
+ if let date = calendar.date(from: components) {
270
+ selectedDate = date
271
+ onDateSelected(date)
272
+ }
273
+ }
274
+ }
275
+
@@ -0,0 +1,28 @@
1
+ import SwiftUI
2
+
3
+ enum DividerDirection {
4
+ case horizontal
5
+ case vertical
6
+ }
7
+
8
+ struct Divider: View {
9
+ var thickness: CGFloat = 1
10
+ var direction: DividerDirection = .horizontal
11
+ var primary: Bool = false
12
+
13
+ var body: some View {
14
+ let color = primary ? LocalColor.Secondary.light : LocalColor.Secondary.light
15
+
16
+ Group {
17
+ if direction == .vertical {
18
+ Rectangle()
19
+ .fill(color)
20
+ .frame(width: thickness)
21
+ } else {
22
+ Rectangle()
23
+ .fill(color)
24
+ .frame(height: thickness)
25
+ }
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,72 @@
1
+ import SwiftUI
2
+ import Combine
3
+
4
+ func Image(
5
+ imageName: String,
6
+ useTemplateRendering: Bool = false
7
+ ) -> Image {
8
+
9
+ guard let bundlePath = Bundle.main.path(forResource: "Resources", ofType: "bundle"),
10
+ let resourcesBundle = Bundle(path: bundlePath) else {
11
+ print("Tuya: Failed to locate Resources.bundle")
12
+ return Image(systemName: "questionmark.circle")
13
+ .renderingMode(useTemplateRendering ? .template : .original)
14
+ }
15
+
16
+ guard let uiImage = UIImage(named: imageName, in: resourcesBundle, compatibleWith: nil) else {
17
+ print("Tuya: Failed to load image: \(imageName) from Resources.bundle")
18
+ return Image(systemName: "questionmark.circle")
19
+ .renderingMode(useTemplateRendering ? .template : .original)
20
+ }
21
+
22
+ return Image(uiImage: uiImage)
23
+ .renderingMode(useTemplateRendering ? .template : .original)
24
+ }
25
+
26
+ class ImageLoader: ObservableObject {
27
+ @Published var image: Image?
28
+
29
+ private var cancellable: AnyCancellable?
30
+
31
+ func load(from url: URL) {
32
+ cancellable = URLSession.shared.dataTaskPublisher(for: url)
33
+ .map { data, response -> UIImage? in
34
+ return UIImage(data: data)
35
+ }
36
+ .map { uiImage in
37
+ if let uiImage = uiImage {
38
+ return Image(uiImage: uiImage)
39
+ } else {
40
+ return nil
41
+ }
42
+ }
43
+ .replaceError(with: nil)
44
+ .receive(on: DispatchQueue.main)
45
+ .sink { [weak self] in self?.image = $0 }
46
+ }
47
+
48
+ func cancel() {
49
+ cancellable?.cancel()
50
+ }
51
+ }
52
+
53
+ struct WebImage: View {
54
+ @ObservedObject private var loader = ImageLoader()
55
+ let url: URL
56
+ let placeholderImageName: String
57
+
58
+ var body: some View {
59
+ if let image = loader.image {
60
+ image
61
+ .resizable()
62
+ .scaledToFit()
63
+ } else {
64
+ Image(imageName: placeholderImageName)
65
+ .resizable()
66
+ .scaledToFit()
67
+ .onAppear {
68
+ loader.load(from: url)
69
+ }
70
+ }
71
+ }
72
+ }