@rentlydev/rently-tuya 0.2.1 → 0.2.3

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 (68) hide show
  1. package/android/src/main/java/com/rentlytuya/RentlyTuyaModule.kt +10 -0
  2. package/android/src/main/java/com/rentlytuya/alerts/PermissionAlert.kt +2 -2
  3. package/android/src/main/java/com/rentlytuya/components/AnchorButton.kt +4 -2
  4. package/android/src/main/java/com/rentlytuya/components/Button.kt +5 -4
  5. package/android/src/main/java/com/rentlytuya/components/CustomDatePicker.kt +9 -7
  6. package/android/src/main/java/com/rentlytuya/components/Divider.kt +1 -5
  7. package/android/src/main/java/com/rentlytuya/components/Label.kt +1 -1
  8. package/android/src/main/java/com/rentlytuya/dashboard/AdvancedSettings.kt +11 -9
  9. package/android/src/main/java/com/rentlytuya/dashboard/Dashboard.kt +4 -4
  10. package/android/src/main/java/com/rentlytuya/dashboard/DoorbellSettings.kt +125 -103
  11. package/android/src/main/java/com/rentlytuya/dashboard/FirmwareUpdate.kt +5 -8
  12. package/android/src/main/java/com/rentlytuya/dashboard/Messages.kt +3 -4
  13. package/android/src/main/java/com/rentlytuya/dashboard/NavController.kt +28 -13
  14. package/android/src/main/java/com/rentlytuya/dashboard/OfflineScreen.kt +12 -12
  15. package/android/src/main/java/com/rentlytuya/dashboard/Playback.kt +3 -3
  16. package/android/src/main/java/com/rentlytuya/tuya/Settings.kt +28 -1
  17. package/android/src/main/java/com/rentlytuya/tuya/Tuya.kt +6 -1
  18. package/android/src/main/java/com/rentlytuya/ui/theme/LocalColor.kt +34 -21
  19. package/android/src/main/java/com/rentlytuya/ui/theme/Theme.kt +13 -1
  20. package/android/src/main/java/com/rentlytuya/util/KeylessModule.kt +16 -4
  21. package/android/src/main/res/drawable/update_complete.png +0 -0
  22. package/android/src/main/res/values/strings.xml +4 -2
  23. package/ios/components/Alert.swift +5 -7
  24. package/ios/components/AnchorButton.swift +2 -0
  25. package/ios/components/Button.swift +17 -2
  26. package/ios/components/CustomDatePicker.swift +5 -5
  27. package/ios/components/Label.swift +6 -1
  28. package/ios/dashboard/AdvanceSettings.swift +5 -5
  29. package/ios/dashboard/Dashboard.swift +43 -6
  30. package/ios/dashboard/FirmwareSettings.swift +11 -9
  31. package/ios/dashboard/Messages.swift +5 -3
  32. package/ios/dashboard/NavigationController.swift +51 -8
  33. package/ios/dashboard/OfflineScreen.swift +5 -7
  34. package/ios/dashboard/Playback.swift +7 -5
  35. package/ios/dashboard/PreviewManager.swift +20 -4
  36. package/ios/dashboard/Settings.swift +39 -21
  37. package/ios/generated/RNRentlyTuyaSpec/RNRentlyTuyaSpec.h +30 -0
  38. package/ios/icons/cloud.png +0 -0
  39. package/ios/icons/cloud@2x.png +0 -0
  40. package/ios/icons/cloud@3x.png +0 -0
  41. package/ios/icons/down_update.png +0 -0
  42. package/ios/icons/down_update@2x.png +0 -0
  43. package/ios/icons/down_update@3x.png +0 -0
  44. package/ios/listener/KeylessListener.swift +11 -5
  45. package/ios/listener/RentlyTuya.mm +6 -1
  46. package/ios/listener/RentlyTuyaImpl.swift +11 -1
  47. package/ios/theme/LocalColor.swift +66 -20
  48. package/ios/theme/Theme.swift +162 -25
  49. package/ios/tuya/CameraManager.swift +1 -1
  50. package/ios/tuya/Tuya.swift +8 -0
  51. package/ios/utils/PermissionManager.swift +41 -0
  52. package/lib/commonjs/NativeRentlyTuya.js.map +1 -1
  53. package/lib/commonjs/index.js.map +1 -1
  54. package/lib/module/NativeRentlyTuya.js.map +1 -1
  55. package/lib/module/index.js.map +1 -1
  56. package/lib/typescript/commonjs/src/NativeRentlyTuya.d.ts +5 -0
  57. package/lib/typescript/commonjs/src/NativeRentlyTuya.d.ts.map +1 -1
  58. package/lib/typescript/commonjs/src/index.d.ts +5 -0
  59. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  60. package/lib/typescript/module/src/NativeRentlyTuya.d.ts +5 -0
  61. package/lib/typescript/module/src/NativeRentlyTuya.d.ts.map +1 -1
  62. package/lib/typescript/module/src/index.d.ts +5 -0
  63. package/lib/typescript/module/src/index.d.ts.map +1 -1
  64. package/package.json +1 -1
  65. package/src/NativeRentlyTuya.ts +5 -0
  66. package/src/index.tsx +5 -0
  67. package/android/src/main/res/drawable/green_complete.png +0 -0
  68. package/android/src/main/res/drawable/white_complete.png +0 -0
@@ -19,6 +19,9 @@ struct CustomButton: View {
19
19
  var secondary: Bool = false
20
20
  var tertiary: Bool = false
21
21
  var black: Bool = false
22
+
23
+ //disabled Button Color
24
+ var greyDisabled: Bool = false
22
25
 
23
26
  // Text/Border Color
24
27
  var textColor: Color = .black
@@ -42,7 +45,7 @@ struct CustomButton: View {
42
45
  if primary {
43
46
  return LocalColor.Primary.medium
44
47
  } else if secondary {
45
- return Color(red: 0.953, green: 0.467, blue: 0.529)
48
+ return Color(hex: "#EF4343")
46
49
  } else if tertiary {
47
50
  return LocalColor.Monochrome.regular
48
51
  } else if black {
@@ -52,6 +55,18 @@ struct CustomButton: View {
52
55
  }
53
56
  }
54
57
 
58
+ var disabledButtonColor: Color? {
59
+ if greyDisabled {
60
+ return Color(hex: "#6B7280")
61
+ } else if black {
62
+ return LocalColor.Monochrome.black
63
+ }
64
+ else {
65
+ return LocalColor.Primary.light
66
+ }
67
+
68
+ }
69
+
55
70
  var body: some View {
56
71
 
57
72
  let font: Font = {
@@ -97,7 +112,7 @@ struct CustomButton: View {
97
112
  .frame(maxWidth: .infinity)
98
113
  }
99
114
  .padding()
100
- .background(buttonColor)
115
+ .background( (Tuya.shared.darkThemefinal && !secondary) ? disabledButtonColor ?? buttonColor : buttonColor)
101
116
  .opacity(disabled ? 0.5 : 1)
102
117
  .cornerRadius(cornerRadius)
103
118
  .overlay(
@@ -52,7 +52,7 @@ struct CustomDatePicker: View {
52
52
  Spacer()
53
53
  }
54
54
  .frame(maxWidth: .infinity)
55
- .background(LocalColor.Main.dark)
55
+ .background(Tuya.shared.darkThemefinal ? Color(hex: "#242526") : LocalColor.Main.dark)
56
56
 
57
57
  HStack {
58
58
  Button(action: {
@@ -70,7 +70,7 @@ struct CustomDatePicker: View {
70
70
  Label(
71
71
  title: formatMonthYear(date: displayedDate),
72
72
  xl18: true,
73
- black: true,
73
+ blackColor: true,
74
74
  bold: true
75
75
  )
76
76
 
@@ -93,7 +93,7 @@ struct CustomDatePicker: View {
93
93
  VStack {
94
94
  Spacer()
95
95
  ProgressView()
96
- .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.black))
96
+ .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.blackColor))
97
97
  Spacer()
98
98
  }
99
99
  .frame(maxWidth: .infinity)
@@ -117,7 +117,7 @@ struct CustomDatePicker: View {
117
117
  id: "DatePicker_Cancel",
118
118
  title: "Cancel",
119
119
  l: true,
120
- secondary: true,
120
+ paleWhite: true,
121
121
  center: true
122
122
  ) {
123
123
  onCancel()
@@ -205,7 +205,7 @@ struct CalendarView: View {
205
205
  .font(.footnote)
206
206
  .frame(width: 30, height: 30)
207
207
  .background(isSelected ? LocalColor.Main.dark : LocalColor.Monochrome.transparent)
208
- .foregroundColor(isSelected ? LocalColor.Monochrome.white : (isAvailable ? LocalColor.Monochrome.black : LocalColor.Monochrome.regular))
208
+ .foregroundColor(isSelected ? LocalColor.Monochrome.whiteColor : (isAvailable ? LocalColor.Monochrome.blackColor : LocalColor.Monochrome.greyColor))
209
209
  .overlay(
210
210
  Circle()
211
211
  .stroke(isAvailable ? LocalColor.Main.dark : LocalColor.Monochrome.transparent, lineWidth: 1)
@@ -22,7 +22,10 @@ struct Label: View {
22
22
  var lightGrey: Bool = false
23
23
  var grey: Bool = false
24
24
  var white: Bool = false
25
+ var whiteColor: Bool = false
25
26
  var black: Bool = false
27
+ var blackColor: Bool = false
28
+ var greyColor: Bool = false
26
29
  var customColor: Color? = nil
27
30
 
28
31
  // Font Weight Options
@@ -58,8 +61,10 @@ struct Label: View {
58
61
  if secondary { return LocalColor.Primary.secondary }
59
62
  if lightGrey { return LocalColor.Monochrome.regular }
60
63
  if grey { return LocalColor.Monochrome.medium }
61
- if white { return LocalColor.Monochrome.white }
64
+ if white { return LocalColor.Monochrome.whiteColor }
62
65
  if black { return LocalColor.Monochrome.black }
66
+ if blackColor { return LocalColor.Monochrome.blackColor }
67
+ if greyColor { return LocalColor.Monochrome.greyColor }
63
68
  return LocalColor.Primary.light
64
69
  }()
65
70
 
@@ -64,11 +64,11 @@ struct StorageSettings: View {
64
64
  VStack(alignment: .leading) {
65
65
  Text("Note:")
66
66
  .font(.custom(LocalFont.FontFamily.bold, size: LocalFont.FontSize.L))
67
- .foregroundColor(LocalColor.Monochrome.black)
67
+ .foregroundColor(LocalColor.Monochrome.greyColor)
68
68
  +
69
69
  Text(" Formatting will delete all recorded activities on the SD Card.")
70
70
  .font(.custom(LocalFont.FontFamily.semiBold, size: LocalFont.FontSize.L))
71
- .foregroundColor(LocalColor.Monochrome.black)
71
+ .foregroundColor(LocalColor.Monochrome.greyColor)
72
72
  Spacer()
73
73
  HStack {
74
74
  Spacer()
@@ -76,7 +76,7 @@ struct StorageSettings: View {
76
76
  id: "FormatSDCard",
77
77
  title: "Format",
78
78
  secondary: true,
79
- textColor: LocalColor.Monochrome.white,
79
+ textColor: LocalColor.Monochrome.whiteColor,
80
80
  semiBold: true,
81
81
  disabled: tuya.sdCardStatus == 4
82
82
  ) {
@@ -107,7 +107,7 @@ struct Item: View {
107
107
  id: title,
108
108
  title: title,
109
109
  l: true,
110
- black: true,
110
+ grey: true,
111
111
  semiBold: true
112
112
  )
113
113
  Spacer()
@@ -116,7 +116,7 @@ struct Item: View {
116
116
  id: value,
117
117
  title: value,
118
118
  l: true,
119
- black: true,
119
+ lightGrey: true,
120
120
  medium: true,
121
121
  right: true,
122
122
  maxLines: 3
@@ -15,6 +15,7 @@ struct Dashboard: View {
15
15
  @Binding var currentScreen: ScreenState
16
16
  @State private var isDoorbellControlVisible = true
17
17
  @State private var isPermissionDisclaimerAlertVisible = false
18
+ @State private var permissionType: String = "microphone"
18
19
  @EnvironmentObject var orientationManager: OrientationManager
19
20
 
20
21
  var body: some View {
@@ -32,7 +33,8 @@ struct Dashboard: View {
32
33
  if tuya.isConnected {
33
34
  DoorbellControls(
34
35
  isDoorbellControlVisible: $isDoorbellControlVisible,
35
- isPermissionDisclaimerAlertVisible: $isPermissionDisclaimerAlertVisible
36
+ isPermissionDisclaimerAlertVisible: $isPermissionDisclaimerAlertVisible,
37
+ permissionType: $permissionType
36
38
  )
37
39
  .padding(.bottom, 10)
38
40
  .alert(
@@ -46,7 +48,7 @@ struct Dashboard: View {
46
48
  }
47
49
  .frame(maxWidth: .infinity, maxHeight: .infinity)
48
50
 
49
- BottomBar(currentScreen: $currentScreen)
51
+ BottomBar(currentScreen: $currentScreen, isPermissionDisclaimerAlertVisible: $isPermissionDisclaimerAlertVisible, permissionType: $permissionType)
50
52
  .alert(
51
53
  isPresented: $tuya.isRecordingFailure,
52
54
  content: {
@@ -75,6 +77,21 @@ struct Dashboard: View {
75
77
  )
76
78
  }
77
79
 
80
+ VStack {
81
+ }
82
+ .alert(isPresented: $isPermissionDisclaimerAlertVisible,
83
+ content: {
84
+ getAlert(
85
+ title: "Permission Request",
86
+ message: "Please provide permission to access your \(permissionType)",
87
+ primaryButtonTitle: "Open Settings",
88
+ secondaryButtonTitle: "Cancel") {
89
+ if let url = URL(string: UIApplication.openSettingsURLString) {
90
+ UIApplication.shared.open(url)
91
+ }
92
+ }
93
+ }
94
+ )
78
95
  }
79
96
  .background(LocalColor.Monochrome.black)
80
97
  .onAppear(perform: handleOnAppear)
@@ -129,7 +146,7 @@ struct Dashboard: View {
129
146
  }
130
147
 
131
148
  if tuya.isConnected {
132
- tuya.enableMute(enable: false, type: .preview)
149
+ tuya.enableMute(enable: tuya.doorbell_setting ?? false, type: .preview)
133
150
  }
134
151
 
135
152
  orientationManager.updateOrientationFlag()
@@ -165,6 +182,7 @@ struct DoorbellControls: View {
165
182
  @ObservedObject var tuya = Tuya.shared
166
183
  @Binding var isDoorbellControlVisible: Bool
167
184
  @Binding var isPermissionDisclaimerAlertVisible: Bool
185
+ @Binding var permissionType: String
168
186
  @EnvironmentObject var orientationManager: OrientationManager
169
187
 
170
188
  private var batteryIcon: String {
@@ -219,7 +237,8 @@ struct DoorbellControls: View {
219
237
  title: tuya.isMicOn ? "Tap to mute" : "Tap to speak",
220
238
  l: true,
221
239
  tertiary: !tuya.isMicOn,
222
- textColor: LocalColor.Monochrome.white,
240
+ greyDisabled: !tuya.isMicOn,
241
+ textColor: Color.white,
223
242
  medium: tuya.isMicOn,
224
243
  semiBold: true,
225
244
  cornerRadius: 40,
@@ -228,11 +247,17 @@ struct DoorbellControls: View {
228
247
  if tuya.isMicOn {
229
248
  tuya.stopTalk()
230
249
  } else {
250
+ PermissionManager.request(.microphone, granted: {
251
+ tuya.startTalk()
252
+ }, denied: {
253
+ permissionType = "microphone"
254
+ isPermissionDisclaimerAlertVisible = true
255
+ }
256
+ )
231
257
  // The speaker needs to be un muted when the mic is turned on.
232
258
  if tuya.isMuted {
233
259
  tuya.enableMute(enable: false, type: .preview)
234
260
  }
235
- tuya.startTalk()
236
261
  }
237
262
  }
238
263
  .frame(width: 185, height: 70)
@@ -279,6 +304,8 @@ struct BottomBar: View {
279
304
 
280
305
  @ObservedObject var tuya = Tuya.shared
281
306
  @Binding var currentScreen: ScreenState
307
+ @Binding var isPermissionDisclaimerAlertVisible: Bool
308
+ @Binding var permissionType: String
282
309
  @EnvironmentObject var orientationManager: OrientationManager
283
310
 
284
311
  var body: some View {
@@ -310,7 +337,12 @@ struct BottomBar: View {
310
337
  print("Camera not connected. Screenshot action disabled.")
311
338
  return
312
339
  }
313
- tuya.screenshot()
340
+ PermissionManager.request(.photos) {
341
+ tuya.screenshot()
342
+ } denied: {
343
+ permissionType = "Photos Library"
344
+ isPermissionDisclaimerAlertVisible = true
345
+ }
314
346
  }
315
347
  )
316
348
 
@@ -328,7 +360,12 @@ struct BottomBar: View {
328
360
  if tuya.isRecording {
329
361
  tuya.stopRecording()
330
362
  } else {
363
+ PermissionManager.request(.photos) {
331
364
  tuya.startRecording()
365
+ } denied: {
366
+ permissionType = "Photos Library"
367
+ isPermissionDisclaimerAlertVisible = true
368
+ }
332
369
  }
333
370
  }
334
371
  )
@@ -15,13 +15,13 @@ struct FirmwareSettings: View {
15
15
  if tuya.isFirmwareUpdateInProgress {
16
16
  ZStack {
17
17
  Circle()
18
- .stroke(LocalColor.Primary.medium.opacity(0.2), lineWidth: 6)
18
+ .stroke(LocalColor.Main.dark.opacity(0.2), lineWidth: 6)
19
19
  .frame(width: 132, height: 132)
20
20
  .padding(20)
21
21
 
22
22
  Circle()
23
23
  .trim(from: 0.0, to: CGFloat(tuya.firmwareUpdateProgress) / 100)
24
- .stroke(LocalColor.Primary.medium, style: StrokeStyle(lineWidth: 6, lineCap: .round))
24
+ .stroke(LocalColor.Main.dark, style: StrokeStyle(lineWidth: 6, lineCap: .round))
25
25
  .rotationEffect(.degrees(-90))
26
26
  .frame(width: 132, height: 132)
27
27
  .padding(20)
@@ -43,7 +43,7 @@ struct FirmwareSettings: View {
43
43
  Spacer()
44
44
  Label(title: tuya.firmwareUpdateProgress >= 50 && tuya.firmwareUpdateProgress < 100 ? "Please keep the doorbell powered on while we complete this update. Thank you for your patience." : "This might take a few minutes. During this time you will not be able to use your video doorbell.",
45
45
  l: true,
46
- black: true,
46
+ blackColor: true,
47
47
  center: true)
48
48
  .padding(20)
49
49
  }
@@ -61,26 +61,26 @@ struct FirmwareSettings: View {
61
61
  Label(
62
62
  title: "Current Firmware Version:",
63
63
  l: true,
64
- black: true,
64
+ grey: true,
65
65
  semiBold: true
66
66
  )
67
67
  Label(
68
68
  title: (tuya.firmwareNewVersion != nil) ? "New Version Available:" : "",
69
69
  l: true,
70
- black: true,
70
+ grey: true,
71
71
  semiBold: true
72
72
  )
73
73
  VStack(alignment: .leading, spacing: 0) {
74
74
  Label(
75
75
  title: Tuya.shared.whatsNew != nil ? "What's new?" : "",
76
76
  l: true,
77
- black: true,
77
+ grey: true,
78
78
  semiBold: true
79
79
  )
80
80
  Label(
81
81
  title: Tuya.shared.whatsNew ?? "",
82
82
  l: true,
83
- black: true,
83
+ grey: true,
84
84
  semiBold: true
85
85
  )
86
86
  .padding(12)
@@ -91,13 +91,14 @@ struct FirmwareSettings: View {
91
91
  Label(
92
92
  title: Tuya.shared.firmwareVersion ?? "",
93
93
  l: true,
94
- black: true,
94
+ lightGrey: true,
95
95
  semiBold: true
96
96
  )
97
97
 
98
98
  Label(
99
99
  title: Tuya.shared.firmwareNewVersion ?? "",
100
100
  l: true,
101
+ lightGrey: true,
101
102
  semiBold: true
102
103
  )
103
104
  Spacer()
@@ -146,7 +147,8 @@ struct FirmwareSettings: View {
146
147
  id: "UpdateFirmware",
147
148
  title: "Update Firmware",
148
149
  l: true,
149
- textColor: LocalColor.Monochrome.white,
150
+ greyDisabled: tuya.isAutomaticUpdateEnabled || !tuya.isFirmwareUpdateAvailable || tuya.isFirmwareUpdateInProgress,
151
+ textColor: LocalColor.Monochrome.whiteColor,
150
152
  medium: true,
151
153
  semiBold: true,
152
154
  disabled: tuya.isAutomaticUpdateEnabled || !tuya.isFirmwareUpdateAvailable || tuya.isFirmwareUpdateInProgress,
@@ -24,7 +24,7 @@ struct Messages: View {
24
24
  ZStack {
25
25
  if tuya.messagesLoader && messages.isEmpty {
26
26
  ProgressView()
27
- .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.black))
27
+ .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.blackColor))
28
28
  .frame(maxWidth: .infinity, maxHeight: .infinity)
29
29
  } else if messages.isEmpty {
30
30
  NoMessages()
@@ -157,6 +157,7 @@ struct NoMessages: View {
157
157
  Label(
158
158
  id: "noMessages",
159
159
  title: "No activity available at the moment.",
160
+ blackColor: true,
160
161
  bold: true,
161
162
  maxLines: 2
162
163
  )
@@ -176,13 +177,14 @@ struct MessageItem: View {
176
177
  Label(
177
178
  title: formattedDateTime ?? message.dateTime,
178
179
  m: true,
179
- black: true
180
+ lightGrey: true
180
181
  )
181
182
  .padding(.bottom, 3)
182
183
 
183
184
  Label(
184
185
  title: (message.attachPic != nil) ? message.msgContent : "Unable to capture detected events because the doorbell's battery is too low. Please charge it to ensure events are detected and recorded.",
185
- l: true
186
+ l: true,
187
+ grey: true
186
188
  )
187
189
  .padding(.bottom, 4)
188
190
 
@@ -5,7 +5,7 @@ enum ScreenState: String {
5
5
  case playback = "Playback"
6
6
  case messages = "Activity History"
7
7
  case settings = "Settings"
8
- case advancedSettings = "Advanced Settings"
8
+ case advancedSettings = "Device Information"
9
9
  case storageSettings = "Activity Storage"
10
10
  case firmwareUpdateSettings = "Firmware Update"
11
11
  }
@@ -22,18 +22,38 @@ struct NavigationController: View {
22
22
  @State private var updateSettingsTask: Task<Void, Never>? = nil
23
23
  @EnvironmentObject var orientationManager: OrientationManager
24
24
  @ObservedObject var tuya = Tuya.shared
25
+ @Environment(\.colorScheme) private var colorScheme
26
+ @State private var themeUpdateTrigger: Int = 0
25
27
 
26
28
  private var topBarTitle: String {
27
29
  if isFirmwareUpdateSettings {
28
30
  return tuya.isFirmwareUpdateInProgress ? "Update Firmware" : "Firmware Version"
29
31
  }
30
- if isAdvancedSettings { return "Advanced Settings" }
32
+ if isAdvancedSettings { return "Device Information" }
31
33
  if isStorageSettings { return "Activity Storage" }
32
34
  return currentScreen == .dashboard ? (tuya.device?.deviceModel.name ?? "Doorbell") : currentScreen.rawValue
33
35
  }
34
36
 
35
37
  private var isSpecialTitle: Bool {
36
- [.settings, .messages, .advancedSettings, .storageSettings, .firmwareUpdateSettings].contains(currentScreen)
38
+ [.settings, .messages, .advancedSettings, .storageSettings, .firmwareUpdateSettings, .playback].contains(currentScreen)
39
+ }
40
+
41
+ private func onThemeChanged(_ scheme: ColorScheme) {
42
+ guard tuya.useSystemTheme else { return }
43
+ DispatchQueue.main.async {
44
+ tuya.currentSystemColorScheme = scheme == .dark ? "dark" : "light"
45
+ tuya.darkThemefinal = tuya.currentSystemColorScheme == "dark"
46
+
47
+ Themes.configureTheme(for: tuya.flavour, darkThemeEnabled: tuya.darkThemefinal)
48
+
49
+ if let windowScene = UIApplication.shared.connectedScenes
50
+ .compactMap({ $0 as? UIWindowScene })
51
+ .first(where: { $0.activationState == .foregroundActive }),
52
+ let window = windowScene.windows.first(where: { $0.isKeyWindow }) {
53
+ window.overrideUserInterfaceStyle = tuya.darkThemefinal ? .dark : .light
54
+ }
55
+ themeUpdateTrigger += 1
56
+ }
37
57
  }
38
58
 
39
59
  var body: some View {
@@ -68,8 +88,12 @@ struct NavigationController: View {
68
88
  } else if currentScreen == .dashboard {
69
89
  AppUtility.disconnectAndClose()
70
90
  } else {
71
- isSettings = false
72
- currentScreen = .dashboard
91
+ if Tuya.shared.doorbell_setting ?? false {
92
+ AppUtility.disconnectAndClose()
93
+ } else {
94
+ isSettings = false
95
+ currentScreen = .dashboard
96
+ }
73
97
  }
74
98
  }
75
99
  }
@@ -85,6 +109,11 @@ struct NavigationController: View {
85
109
  }
86
110
  }
87
111
  )
112
+ .onAppear {
113
+ if currentScreen == .dashboard && Tuya.shared.doorbell_setting ?? false {
114
+ currentScreen = .settings
115
+ }
116
+ }
88
117
  }
89
118
 
90
119
  ZStack {
@@ -125,6 +154,7 @@ struct NavigationController: View {
125
154
  }
126
155
  }
127
156
  }
157
+ .id(themeUpdateTrigger)
128
158
  .onChange(of: currentScreen) { newValue in
129
159
  HeapAnalytics.trackEvent(eventName: "\(newValue.rawValue) Screen")
130
160
  }
@@ -143,7 +173,15 @@ struct NavigationController: View {
143
173
  }
144
174
  }
145
175
  }
176
+ .onChange(of: colorScheme) { newScheme in
177
+ onThemeChanged(newScheme)
178
+ }
146
179
  .onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in
180
+ if tuya.useSystemTheme {
181
+ let interfaceStyle = UITraitCollection.current.userInterfaceStyle
182
+ tuya.currentSystemColorScheme = interfaceStyle == .dark ? "dark" : "light"
183
+ onThemeChanged(interfaceStyle == .dark ? .dark : .light)
184
+ }
147
185
  if currentScreen == .playback {
148
186
  tuya.pausePlayback()
149
187
  } else {
@@ -151,6 +189,11 @@ struct NavigationController: View {
151
189
  }
152
190
  }
153
191
  .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
192
+ if tuya.useSystemTheme {
193
+ let interfaceStyle = UITraitCollection.current.userInterfaceStyle
194
+ tuya.currentSystemColorScheme = interfaceStyle == .dark ? "dark" : "light"
195
+ onThemeChanged(interfaceStyle == .dark ? .dark : .light)
196
+ }
154
197
  if currentScreen == .dashboard {
155
198
  tuya.connect()
156
199
  }
@@ -171,7 +214,7 @@ struct TopBar: View {
171
214
  title: title,
172
215
  xl20: true,
173
216
  white: !isSpecialTitle,
174
- black: isSpecialTitle,
217
+ greyColor: isSpecialTitle,
175
218
  semiBold: true
176
219
  )
177
220
 
@@ -184,7 +227,7 @@ struct TopBar: View {
184
227
  .resizable()
185
228
  .aspectRatio(contentMode: .fit)
186
229
  .frame(width: 22, height: 22)
187
- .foregroundColor(isSpecialTitle ? LocalColor.Monochrome.black : LocalColor.Monochrome.white)
230
+ .foregroundColor(isSpecialTitle ? LocalColor.Monochrome.greyColor : LocalColor.Monochrome.whiteColor)
188
231
  }
189
232
  .padding(.leading, 5)
190
233
 
@@ -199,7 +242,7 @@ struct TopBar: View {
199
242
  .resizable()
200
243
  .aspectRatio(contentMode: .fit)
201
244
  .frame(width: 24, height: 24)
202
- .foregroundColor(title == "Activity History" ? LocalColor.Monochrome.grey : LocalColor.Monochrome.white)
245
+ .foregroundColor(title == "Activity History" || title == "Playback" ? LocalColor.Monochrome.greyColor : LocalColor.Monochrome.whiteColor)
203
246
  }
204
247
  .padding(.trailing, 5)
205
248
  }
@@ -70,17 +70,15 @@ struct OfflineScreen: View {
70
70
  center: true,
71
71
  underLine: true
72
72
  ) {
73
- if let cameraType = tuya.cameraType {
74
- KeylessListener.emitter.resetWifiForDoorbell(
75
- withDeviceID: cameraType.devId) { success, message in
76
- if success {
77
- print("Tuya: Successfully navigated to the 'Add Doorbell' screen.")
78
- AppUtility.disconnectAndClose()
73
+ KeylessListener.emitter.resetWifiForDoorbell(
74
+ withTuyaProductName: tuya.tuyaProductName ?? "") { success, message in
75
+ if success {
76
+ print("Tuya: Successfully navigated to the 'Add Doorbell' screen.")
77
+ AppUtility.disconnectAndClose()
79
78
  } else {
80
79
  print("Tuya: Failed to navigate to the 'Add Doorbell' screen.")
81
80
  }
82
81
  }
83
- }
84
82
  }
85
83
  .frame(maxWidth: .infinity, alignment: .center)
86
84
  .padding(.bottom, 5)
@@ -86,7 +86,7 @@ struct Playback: View {
86
86
 
87
87
  if tuya.playbackLoader {
88
88
  ProgressView()
89
- .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.black))
89
+ .progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.blackColor))
90
90
  }
91
91
 
92
92
  CustomDatePicker(
@@ -293,7 +293,7 @@ struct PlaybackList: View {
293
293
  id: "noPlaybackVideos",
294
294
  title: "No Playback videos available at the moment.",
295
295
  xl18: true,
296
- black: true,
296
+ blackColor: true,
297
297
  semiBold: true,
298
298
  center: true
299
299
  )
@@ -342,7 +342,8 @@ struct VideoItem: View {
342
342
  Label(
343
343
  title: "\(convertTimestampToTime(item["startTime"] as? Int))",
344
344
  l: true,
345
- primary: true,
345
+ grey: !isSelected,
346
+ white: isSelected,
346
347
  bold: true,
347
348
  left: true
348
349
  )
@@ -350,7 +351,8 @@ struct VideoItem: View {
350
351
  Label(
351
352
  title: ("Duration: \(calculateVideoDuration(from: item["startTime"] as? Int, to: item["endTime"] as? Int))"),
352
353
  m: true,
353
- secondary: true,
354
+ lightGrey: !isSelected,
355
+ white: isSelected,
354
356
  left: true
355
357
  )
356
358
  .padding(.top, 5)
@@ -360,7 +362,7 @@ struct VideoItem: View {
360
362
  Spacer()
361
363
  }
362
364
  .frame(maxWidth: /*@START_MENU_TOKEN@*/.infinity/*@END_MENU_TOKEN@*/)
363
- .background(isSelected ? LocalColor.Secondary.light : LocalColor.Monochrome.white)
365
+ .background(isSelected ? LocalColor.Main.dark : LocalColor.Monochrome.white)
364
366
  .cornerRadius(5)
365
367
  .padding(.top, 8)
366
368
  .padding(.horizontal, 10)
@@ -102,15 +102,31 @@ struct PreviewView: UIViewRepresentable {
102
102
  }
103
103
  }
104
104
 
105
- func openLivePreview(appFlavor: String) {
106
-
105
+ func openLivePreview(appFlavor: String, darkThemeEnabled: Bool = false, useSystemTheme: Bool = false, currentSystemColorScheme: String = "light") {
106
+ Tuya.shared.darkThemeEnabled = darkThemeEnabled
107
+ Tuya.shared.useSystemTheme = useSystemTheme
108
+ Tuya.shared.currentSystemColorScheme = currentSystemColorScheme
109
+ if useSystemTheme {
110
+ let interfaceStyle = UITraitCollection.current.userInterfaceStyle
111
+ Tuya.shared.currentSystemColorScheme = interfaceStyle == .dark ? "dark" : "light"
112
+ }
113
+ Tuya.shared.darkThemefinal = useSystemTheme ? (Tuya.shared.currentSystemColorScheme == "dark") : darkThemeEnabled
107
114
  DispatchQueue.main.async {
108
- Themes.configureTheme(for: appFlavor)
115
+ Themes.configureTheme(for: appFlavor, darkThemeEnabled: Tuya.shared.darkThemefinal)
116
+
117
+ if let windowScene = UIApplication.shared.connectedScenes
118
+ .compactMap({ $0 as? UIWindowScene })
119
+ .first(where: { $0.activationState == .foregroundActive }),
120
+ let window = windowScene.windows.first(where: { $0.isKeyWindow }) {
121
+ window.overrideUserInterfaceStyle = Tuya.shared.darkThemefinal ? .dark : .light
122
+ }
123
+
109
124
  let orientationManager = OrientationManager()
110
125
  let dashboardView = NavigationController().environmentObject(orientationManager)
111
126
  let hostingController = UIHostingController(rootView: dashboardView)
112
127
  hostingController.modalPresentationStyle = .fullScreen
113
- if let windowScene = UIApplication.shared.connectedScenes
128
+
129
+ if let windowScene = UIApplication.shared.connectedScenes
114
130
  .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene,
115
131
  let rootVC = windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController {
116
132
  rootVC.present(hostingController, animated: true, completion: nil)