@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.
- package/LICENSE +20 -0
- package/README.md +281 -0
- package/android/build.gradle +182 -0
- package/android/gradle.properties +7 -0
- package/android/libs/airbrake-android-1.4.0.jar +0 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/AndroidManifestNew.xml +25 -0
- package/android/src/main/java/com/rentlytuya/RentlyTuyaModule.kt +503 -0
- package/android/src/main/java/com/rentlytuya/RentlyTuyaPackage.kt +18 -0
- package/android/src/main/java/com/rentlytuya/TuyaActivity.kt +45 -0
- package/android/src/main/java/com/rentlytuya/alerts/FormatSDCardAlert.kt +83 -0
- package/android/src/main/java/com/rentlytuya/alerts/PermissionAlert.kt +91 -0
- package/android/src/main/java/com/rentlytuya/alerts/RemoveDoorbellAlert.kt +83 -0
- package/android/src/main/java/com/rentlytuya/alerts/RemoveDoorbellFailureAlert.kt +71 -0
- package/android/src/main/java/com/rentlytuya/alerts/ResetWifiAlert.kt +83 -0
- package/android/src/main/java/com/rentlytuya/alerts/SuccessAlert.kt +74 -0
- package/android/src/main/java/com/rentlytuya/components/Alert.kt +47 -0
- package/android/src/main/java/com/rentlytuya/components/AnchorButton.kt +125 -0
- package/android/src/main/java/com/rentlytuya/components/Button.kt +147 -0
- package/android/src/main/java/com/rentlytuya/components/CustomDatePicker.kt +275 -0
- package/android/src/main/java/com/rentlytuya/components/Divider.kt +53 -0
- package/android/src/main/java/com/rentlytuya/components/EncryptedImageView.kt +59 -0
- package/android/src/main/java/com/rentlytuya/components/Label.kt +155 -0
- package/android/src/main/java/com/rentlytuya/components/LoadingIndicator.kt +75 -0
- package/android/src/main/java/com/rentlytuya/components/Slider.kt +66 -0
- package/android/src/main/java/com/rentlytuya/components/Switch.kt +51 -0
- package/android/src/main/java/com/rentlytuya/components/VideoView.kt +45 -0
- package/android/src/main/java/com/rentlytuya/dashboard/AdvancedSettings.kt +259 -0
- package/android/src/main/java/com/rentlytuya/dashboard/Dashboard.kt +551 -0
- package/android/src/main/java/com/rentlytuya/dashboard/DoorbellSettings.kt +874 -0
- package/android/src/main/java/com/rentlytuya/dashboard/Messages.kt +463 -0
- package/android/src/main/java/com/rentlytuya/dashboard/NavController.kt +358 -0
- package/android/src/main/java/com/rentlytuya/dashboard/OfflineScreen.kt +160 -0
- package/android/src/main/java/com/rentlytuya/dashboard/Playback.kt +685 -0
- package/android/src/main/java/com/rentlytuya/tuya/Messages.kt +234 -0
- package/android/src/main/java/com/rentlytuya/tuya/Playback.kt +385 -0
- package/android/src/main/java/com/rentlytuya/tuya/ScreenCapture.kt +244 -0
- package/android/src/main/java/com/rentlytuya/tuya/Settings.kt +809 -0
- package/android/src/main/java/com/rentlytuya/tuya/Tuya.kt +497 -0
- package/android/src/main/java/com/rentlytuya/ui/theme/LocalColor.kt +80 -0
- package/android/src/main/java/com/rentlytuya/ui/theme/LocalFont.kt +35 -0
- package/android/src/main/java/com/rentlytuya/ui/theme/Theme.kt +34 -0
- package/android/src/main/java/com/rentlytuya/ui/theme/Type.kt +34 -0
- package/android/src/main/java/com/rentlytuya/util/Airbrake.kt +40 -0
- package/android/src/main/java/com/rentlytuya/util/DpConstants.kt +53 -0
- package/android/src/main/java/com/rentlytuya/util/FrescoManager.kt +86 -0
- package/android/src/main/java/com/rentlytuya/util/HeapAnalytics.kt +16 -0
- package/android/src/main/java/com/rentlytuya/util/KeylessModule.kt +81 -0
- package/android/src/main/java/com/rentlytuya/util/PermissionHandler.kt +75 -0
- package/android/src/main/java/com/rentlytuya/util/ReactParamsCheck.kt +152 -0
- package/android/src/main/java/com/rentlytuya/util/Util.kt +128 -0
- package/android/src/main/res/drawable/ic_close.xml +12 -0
- package/android/src/main/res/drawable/ic_launcher_background.xml +170 -0
- package/android/src/main/res/drawable/ic_launcher_foreground.xml +30 -0
- package/android/src/main/res/drawable/img_place_holder.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_action_arrow_backward.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_arrow_backward_white.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_arrow_blue_right.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_calendar.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_camera.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_message.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_play_back.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_record.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_retry.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_setting.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_sound_off.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_sound_on.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_action_arrow_backward.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_arrow_backward_white.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_arrow_blue_right.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_battery_average.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_battery_charging.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_battery_full.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_battery_good.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_battery_low.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_calendar.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_camera.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_message.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_play_back.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_record.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_retry.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_setting.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_sound_off.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_sound_on.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_action_arrow_backward.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_arrow_backward_white.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_arrow_blue_right.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_battery_average.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_battery_charging.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_battery_full.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_battery_good.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_battery_low.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_calendar.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_camera.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_message.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_play_back.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_record.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_retry.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_setting.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_sound_off.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_sound_on.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_action_arrow_backward.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_arrow_backward_white.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_arrow_blue_right.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_battery_average.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_battery_charging.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_battery_full.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_battery_good.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_battery_low.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_calendar.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_camera.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_message.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_play_back.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_record.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_retry.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_setting.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_sound_off.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_sound_on.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_action_arrow_backward.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_arrow_backward_white.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_arrow_blue_right.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_calendar.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_camera.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_message.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_play_back.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_record.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_retry.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_setting.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_sound_off.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_sound_on.png +0 -0
- package/android/src/main/res/font/quicksand_bold.ttf +0 -0
- package/android/src/main/res/font/quicksand_light.ttf +0 -0
- package/android/src/main/res/font/quicksand_medium.ttf +0 -0
- package/android/src/main/res/font/quicksand_regular.ttf +0 -0
- package/android/src/main/res/font/quicksand_semi_bold.ttf +0 -0
- package/android/src/main/res/values/strings.xml +121 -0
- package/android/thingMapping.gradle +200 -0
- package/android/thingMapping.json +2014 -0
- package/ios/components/Alert.swift +54 -0
- package/ios/components/AnchorButton.swift +100 -0
- package/ios/components/Button.swift +118 -0
- package/ios/components/CustomDatePicker.swift +275 -0
- package/ios/components/Divider.swift +28 -0
- package/ios/components/Image.swift +72 -0
- package/ios/components/Label.swift +105 -0
- package/ios/components/Switch.swift +61 -0
- package/ios/dashboard/AdvanceSettings.swift +127 -0
- package/ios/dashboard/Dashboard.swift +354 -0
- package/ios/dashboard/Messages.swift +361 -0
- package/ios/dashboard/NavigationController.swift +173 -0
- package/ios/dashboard/OfflineScreen.swift +109 -0
- package/ios/dashboard/Playback.swift +543 -0
- package/ios/dashboard/PreviewManager.swift +117 -0
- package/ios/dashboard/Settings.swift +672 -0
- package/ios/icons/Charging.png +0 -0
- package/ios/icons/Charging@2x.png +0 -0
- package/ios/icons/Charging@3x.png +0 -0
- package/ios/icons/back_arraow.png +0 -0
- package/ios/icons/back_arraow@2x.png +0 -0
- package/ios/icons/back_arraow@3x.png +0 -0
- package/ios/icons/battery_average.png +0 -0
- package/ios/icons/battery_average@2x.png +0 -0
- package/ios/icons/battery_average@3x.png +0 -0
- package/ios/icons/battery_full.png +0 -0
- package/ios/icons/battery_full@2x.png +0 -0
- package/ios/icons/battery_full@3x.png +0 -0
- package/ios/icons/battery_good.png +0 -0
- package/ios/icons/battery_good@2x.png +0 -0
- package/ios/icons/battery_good@3x.png +0 -0
- package/ios/icons/battery_low.png +0 -0
- package/ios/icons/battery_low@2x.png +0 -0
- package/ios/icons/battery_low@3x.png +0 -0
- package/ios/icons/calendar.png +0 -0
- package/ios/icons/calendar@2x.png +0 -0
- package/ios/icons/calendar@3x.png +0 -0
- package/ios/icons/cloud.png +0 -0
- package/ios/icons/cloud@2x.png +0 -0
- package/ios/icons/cloud@3x.png +0 -0
- package/ios/icons/down_update.png +0 -0
- package/ios/icons/down_update@2x.png +0 -0
- package/ios/icons/down_update@3x.png +0 -0
- package/ios/icons/exit_fullscreen.png +0 -0
- package/ios/icons/exit_fullscreen@2x.png +0 -0
- package/ios/icons/exit_fullscreen@3x.png +0 -0
- package/ios/icons/expand.png +0 -0
- package/ios/icons/fullscreen.png +0 -0
- package/ios/icons/fullscreen@2x.png +0 -0
- package/ios/icons/fullscreen@3x.png +0 -0
- package/ios/icons/image_placeholder.png +0 -0
- package/ios/icons/information.png +0 -0
- package/ios/icons/information@2x.png +0 -0
- package/ios/icons/information@3x.png +0 -0
- package/ios/icons/keyless_Setting.png +0 -0
- package/ios/icons/keyless_Setting@2x.png +0 -0
- package/ios/icons/keyless_Setting@3x.png +0 -0
- package/ios/icons/keyless_back@1x.png +0 -0
- package/ios/icons/keyless_back@2x.png +0 -0
- package/ios/icons/keyless_back@3x.png +0 -0
- package/ios/icons/keyless_filter.png +0 -0
- package/ios/icons/keyless_filter@2x.png +0 -0
- package/ios/icons/keyless_filter@3x.png +0 -0
- package/ios/icons/keyless_message.png +0 -0
- package/ios/icons/keyless_message@2x.png +0 -0
- package/ios/icons/keyless_message@3x.png +0 -0
- package/ios/icons/keyless_pause.png +0 -0
- package/ios/icons/keyless_pause@2x.png +0 -0
- package/ios/icons/keyless_pause@3x.png +0 -0
- package/ios/icons/keyless_photo.png +0 -0
- package/ios/icons/keyless_photo@2x.png +0 -0
- package/ios/icons/keyless_photo@3x.png +0 -0
- package/ios/icons/keyless_play.png +0 -0
- package/ios/icons/keyless_play@2x.png +0 -0
- package/ios/icons/keyless_play@3x.png +0 -0
- package/ios/icons/keyless_play_list.png +0 -0
- package/ios/icons/keyless_play_list@2x.png +0 -0
- package/ios/icons/keyless_play_list@3x.png +0 -0
- package/ios/icons/keyless_play_playback.png +0 -0
- package/ios/icons/keyless_play_playback@2x.png +0 -0
- package/ios/icons/keyless_play_playback@3x.png +0 -0
- package/ios/icons/keyless_record.png +0 -0
- package/ios/icons/keyless_record@2x.png +0 -0
- package/ios/icons/keyless_record@3x.png +0 -0
- package/ios/icons/keyless_record_on.png +0 -0
- package/ios/icons/keyless_record_on@2x.png +0 -0
- package/ios/icons/keyless_record_on@3x.png +0 -0
- package/ios/icons/keyless_sound_off.png +0 -0
- package/ios/icons/keyless_sound_off@2x.png +0 -0
- package/ios/icons/keyless_sound_off@3x.png +0 -0
- package/ios/icons/keyless_sound_on.png +0 -0
- package/ios/icons/keyless_sound_on@2x.png +0 -0
- package/ios/icons/keyless_sound_on@3x.png +0 -0
- package/ios/icons/keyless_speak_off.png +0 -0
- package/ios/icons/keyless_speak_off@2x.png +0 -0
- package/ios/icons/keyless_speak_on.png +0 -0
- package/ios/icons/keyless_speak_on@2x.png +0 -0
- package/ios/icons/keyless_speak_on@3x.png +0 -0
- package/ios/icons/refresh.png +0 -0
- package/ios/icons/refresh@2x.png +0 -0
- package/ios/icons/refresh@3x.png +0 -0
- package/ios/icons/ty_camera_control_hd_normal@2x.png +0 -0
- package/ios/icons/ty_camera_control_hd_normal@3x.png +0 -0
- package/ios/icons/ty_camera_control_sd_normal@2x.png +0 -0
- package/ios/icons/ty_camera_control_sd_normal@3x.png +0 -0
- package/ios/icons/upgrade_success.png +0 -0
- package/ios/icons/upgrade_success@2x.png +0 -0
- package/ios/icons/upgrade_success@3x.png +0 -0
- package/ios/listener/KeylessListener.m +8 -0
- package/ios/listener/KeylessListener.swift +56 -0
- package/ios/listener/RentlyTuya-Bridging-Header.h +5 -0
- package/ios/listener/RentlyTuya.mm +56 -0
- package/ios/listener/RentlyTuya.swift +544 -0
- package/ios/theme/LocalColor.swift +33 -0
- package/ios/theme/LocalFont.swift +32 -0
- package/ios/theme/Theme.swift +71 -0
- package/ios/tuya/CameraManager.swift +296 -0
- package/ios/tuya/SettingsManager.swift +475 -0
- package/ios/tuya/Tuya.swift +570 -0
- package/ios/tuya/TuyaMessages.swift +98 -0
- package/ios/utils/Airbrake.swift +31 -0
- package/ios/utils/AppUtility.swift +76 -0
- package/ios/utils/HeapAnalytics.swift +8 -0
- package/ios/utils/OrientationManager.swift +60 -0
- package/ios/utils/PromiseHandler.swift +36 -0
- package/lib/commonjs/index.js +90 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/module/index.js +83 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +75 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/index.d.ts +75 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/package.json +188 -0
- package/rently-tuya.podspec +52 -0
- package/src/index.tsx +158 -0
@@ -0,0 +1,543 @@
|
|
1
|
+
import SwiftUI
|
2
|
+
import ThingSmartCameraBase
|
3
|
+
import ThingSmartDeviceKit
|
4
|
+
import Combine
|
5
|
+
|
6
|
+
struct Playback: View {
|
7
|
+
|
8
|
+
@ObservedObject var tuya = Tuya.shared
|
9
|
+
@State var selectedDate: Date = Date()
|
10
|
+
@Binding var isDatePickerVisible: Bool
|
11
|
+
|
12
|
+
@State private var isSliderVisible: Bool = false
|
13
|
+
@State private var currentSliderValue: Double = 0
|
14
|
+
@State private var isEditingSlider: Bool = false
|
15
|
+
@State private var timer: Timer? = nil
|
16
|
+
@EnvironmentObject var orientationManager: OrientationManager
|
17
|
+
|
18
|
+
@State private var lastMoveOutDate: Date? = {
|
19
|
+
let dateFormatter = ISO8601DateFormatter()
|
20
|
+
return Tuya.shared.lastMoveoutAt.flatMap { dateFormatter.date(from: $0) }
|
21
|
+
}()
|
22
|
+
|
23
|
+
var body: some View {
|
24
|
+
VStack {
|
25
|
+
if !orientationManager.isLandscape {
|
26
|
+
VideoPlayerView(
|
27
|
+
isSliderVisible: $isSliderVisible,
|
28
|
+
currentSliderValue: $currentSliderValue,
|
29
|
+
isEditingSlider: $isEditingSlider,
|
30
|
+
showSlider: showSlider,
|
31
|
+
removeSlider: removeSlider
|
32
|
+
)
|
33
|
+
|
34
|
+
PlaybackList(
|
35
|
+
currentSliderValue: $currentSliderValue,
|
36
|
+
showSlider: showSlider
|
37
|
+
)
|
38
|
+
|
39
|
+
PlaybackBottomBar(
|
40
|
+
currentSliderValue: $currentSliderValue
|
41
|
+
)
|
42
|
+
.alert(
|
43
|
+
isPresented: $tuya.isScreenshotSuccess,
|
44
|
+
content: {
|
45
|
+
getSuccessAlert(
|
46
|
+
title: "A screenshot has been saved to your photo gallery."
|
47
|
+
)
|
48
|
+
})
|
49
|
+
} else {
|
50
|
+
VideoPlayerView(
|
51
|
+
isSliderVisible: $isSliderVisible,
|
52
|
+
currentSliderValue: $currentSliderValue,
|
53
|
+
isEditingSlider: $isEditingSlider,
|
54
|
+
showSlider: showSlider,
|
55
|
+
removeSlider: removeSlider
|
56
|
+
)
|
57
|
+
.edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
|
58
|
+
}
|
59
|
+
}
|
60
|
+
.onChange(of: orientationManager.isLandscape) { _ in
|
61
|
+
if orientationManager.isLandscape && isDatePickerVisible {
|
62
|
+
isDatePickerVisible = false
|
63
|
+
}
|
64
|
+
}
|
65
|
+
.onAppear {
|
66
|
+
print("Tuya: Harish \(String(describing: lastMoveOutDate))")
|
67
|
+
showSlider()
|
68
|
+
let calendar = Calendar.current
|
69
|
+
let year = calendar.component(.year, from: selectedDate)
|
70
|
+
let month = calendar.component(.month, from: selectedDate)
|
71
|
+
tuya.getAvailableDays(year: UInt(year), month: UInt(month))
|
72
|
+
|
73
|
+
tuya.enableMute(enable: true, type: .preview)
|
74
|
+
if tuya.isPreviewing {
|
75
|
+
tuya.stopPreview()
|
76
|
+
}
|
77
|
+
fetchVideos()
|
78
|
+
tuya.enableMute(enable: false, type: .playback)
|
79
|
+
setupTimer()
|
80
|
+
}
|
81
|
+
.onDisappear {
|
82
|
+
timer?.invalidate()
|
83
|
+
tuya.playbackVideoList = nil
|
84
|
+
isDatePickerVisible = false
|
85
|
+
}
|
86
|
+
|
87
|
+
if tuya.playbackLoader {
|
88
|
+
ProgressView()
|
89
|
+
.progressViewStyle(CircularProgressViewStyle(tint: LocalColor.Monochrome.black))
|
90
|
+
}
|
91
|
+
|
92
|
+
CustomDatePicker(
|
93
|
+
isVisible: $isDatePickerVisible,
|
94
|
+
selectedDate: $selectedDate,
|
95
|
+
availableDays: tuya.recordDays ?? [],
|
96
|
+
minDate: lastMoveOutDate
|
97
|
+
) { date in
|
98
|
+
} onMonthChanged: { date in
|
99
|
+
tuya.getAvailableDays(
|
100
|
+
year: UInt(Calendar.current.component(.year, from: date)),
|
101
|
+
month: UInt(Calendar.current.component(.month, from: date))
|
102
|
+
)
|
103
|
+
} onCancel: {
|
104
|
+
isDatePickerVisible = false
|
105
|
+
} onOk: {
|
106
|
+
isDatePickerVisible = false
|
107
|
+
currentSliderValue = 0
|
108
|
+
fetchVideos()
|
109
|
+
} onAppear: {
|
110
|
+
tuya.getAvailableDays(
|
111
|
+
year: UInt(Calendar.current.component(.year, from: selectedDate)),
|
112
|
+
month: UInt(Calendar.current.component(.month, from: selectedDate))
|
113
|
+
)
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
private func setupTimer() {
|
118
|
+
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
|
119
|
+
updateCurrentSliderValue()
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
private func updateCurrentSliderValue() {
|
124
|
+
guard let selectedItem = tuya.selectedItem,
|
125
|
+
let startTime = selectedItem["startTime"] as? Int,
|
126
|
+
let endTime = selectedItem["endTime"] as? Int else { return }
|
127
|
+
|
128
|
+
if tuya.isPlaybacking && !tuya.isPaused && !tuya.playbackLoader && !isEditingSlider {
|
129
|
+
if currentSliderValue < Double(endTime - startTime) {
|
130
|
+
currentSliderValue += 1
|
131
|
+
} else {
|
132
|
+
tuya.pausePlayback()
|
133
|
+
}
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
private func fetchVideos() {
|
138
|
+
guard Tuya.shared.isConnected else {
|
139
|
+
tuya.isPlaybacking = false
|
140
|
+
print("Tuya: Camera is not connected, hence unable to get the video list and start the playback")
|
141
|
+
return
|
142
|
+
}
|
143
|
+
|
144
|
+
let calendar = Calendar.current
|
145
|
+
let year = calendar.component(.year, from: selectedDate)
|
146
|
+
let month = calendar.component(.month, from: selectedDate)
|
147
|
+
let day = calendar.component(.day, from: selectedDate)
|
148
|
+
|
149
|
+
Tuya.shared.getVideoList(year: UInt(year), month: UInt(month), day: UInt(day))
|
150
|
+
}
|
151
|
+
|
152
|
+
private func showSlider() {
|
153
|
+
withAnimation(.easeInOut(duration: 0.3)) {
|
154
|
+
isSliderVisible = true
|
155
|
+
}
|
156
|
+
|
157
|
+
removeSlider()
|
158
|
+
}
|
159
|
+
|
160
|
+
private func removeSlider() {
|
161
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 8) {
|
162
|
+
if !isEditingSlider {
|
163
|
+
withAnimation(.easeInOut(duration: 0.3)) {
|
164
|
+
isSliderVisible = false
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
struct VideoPlayerView: View {
|
172
|
+
|
173
|
+
@ObservedObject var tuya = Tuya.shared
|
174
|
+
@Binding var isSliderVisible: Bool
|
175
|
+
@Binding var currentSliderValue: Double
|
176
|
+
@Binding var isEditingSlider: Bool
|
177
|
+
var showSlider: () -> Void
|
178
|
+
var removeSlider: () -> Void
|
179
|
+
@EnvironmentObject var orientationManager: OrientationManager
|
180
|
+
|
181
|
+
var body: some View {
|
182
|
+
ZStack {
|
183
|
+
if tuya.isPlaybacking {
|
184
|
+
if tuya.selectedItem == nil {
|
185
|
+
Rectangle()
|
186
|
+
.fill(LocalColor.Monochrome.black)
|
187
|
+
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
188
|
+
} else {
|
189
|
+
PreviewView()
|
190
|
+
|
191
|
+
if isSliderVisible {
|
192
|
+
SliderView(
|
193
|
+
currentSliderValue: $currentSliderValue,
|
194
|
+
isEditingSlider: $isEditingSlider,
|
195
|
+
removeSlider: removeSlider
|
196
|
+
)
|
197
|
+
}
|
198
|
+
}
|
199
|
+
} else {
|
200
|
+
Rectangle()
|
201
|
+
.fill(LocalColor.Monochrome.black)
|
202
|
+
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
203
|
+
}
|
204
|
+
}
|
205
|
+
.onTapGesture {
|
206
|
+
showSlider()
|
207
|
+
}
|
208
|
+
.frame(
|
209
|
+
maxWidth: .infinity,
|
210
|
+
maxHeight: orientationManager.isLandscape ? .infinity : 250
|
211
|
+
)
|
212
|
+
.edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
|
213
|
+
.alert(
|
214
|
+
isPresented: $tuya.isRecordingFailure,
|
215
|
+
content: {
|
216
|
+
getSuccessAlert(
|
217
|
+
title: "Failed to save the recording to your photo gallery."
|
218
|
+
)
|
219
|
+
})
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
struct SliderView: View {
|
224
|
+
|
225
|
+
@ObservedObject var tuya = Tuya.shared
|
226
|
+
@Binding var currentSliderValue: Double
|
227
|
+
@Binding var isEditingSlider: Bool
|
228
|
+
var removeSlider: () -> Void
|
229
|
+
|
230
|
+
var body: some View {
|
231
|
+
VStack {
|
232
|
+
Spacer()
|
233
|
+
|
234
|
+
if let selectedItem = tuya.selectedItem,
|
235
|
+
let startTime = selectedItem["startTime"] as? Int,
|
236
|
+
let endTime = selectedItem["endTime"] as? Int {
|
237
|
+
|
238
|
+
let duration = calculateVideoDuration(from: startTime, to: endTime)
|
239
|
+
|
240
|
+
HStack {
|
241
|
+
Label(
|
242
|
+
title: "\(formatTime(from: currentSliderValue)) / \(duration)",
|
243
|
+
m: true,
|
244
|
+
white: true,
|
245
|
+
left: true
|
246
|
+
)
|
247
|
+
|
248
|
+
Spacer()
|
249
|
+
}
|
250
|
+
.padding(.leading, 4)
|
251
|
+
|
252
|
+
Slider(
|
253
|
+
value: $currentSliderValue,
|
254
|
+
in: 0...Double(endTime - startTime),
|
255
|
+
onEditingChanged: { editing in
|
256
|
+
isEditingSlider = editing
|
257
|
+
if !editing {
|
258
|
+
let playTime = startTime + Int(currentSliderValue)
|
259
|
+
startPlayback(playTime: playTime, startTime: startTime, endTime: endTime)
|
260
|
+
|
261
|
+
removeSlider()
|
262
|
+
}
|
263
|
+
}
|
264
|
+
)
|
265
|
+
.accentColor(LocalColor.Primary.medium)
|
266
|
+
}
|
267
|
+
}
|
268
|
+
.padding()
|
269
|
+
.background(Color.black.opacity(0.4))
|
270
|
+
.frame(maxWidth: .infinity)
|
271
|
+
}
|
272
|
+
|
273
|
+
private func formatTime(from seconds: Double) -> String {
|
274
|
+
let hours = Int(seconds) / 3600
|
275
|
+
let minutes = (Int(seconds) % 3600) / 60
|
276
|
+
let secs = Int(seconds) % 60
|
277
|
+
return String(format: "%02d:%02d:%02d", hours, minutes, secs)
|
278
|
+
}
|
279
|
+
}
|
280
|
+
|
281
|
+
struct PlaybackList: View {
|
282
|
+
|
283
|
+
@ObservedObject var tuya = Tuya.shared
|
284
|
+
@Binding var currentSliderValue: Double
|
285
|
+
var showSlider: () -> Void
|
286
|
+
|
287
|
+
var body: some View {
|
288
|
+
VStack {
|
289
|
+
if tuya.playbackVideoList == nil || tuya.playbackVideoList?.isEmpty == true {
|
290
|
+
VStack {
|
291
|
+
Spacer()
|
292
|
+
Label(
|
293
|
+
id: "noPlaybackVideos",
|
294
|
+
title: "No Playback videos available at the moment.",
|
295
|
+
xl18: true,
|
296
|
+
black: true,
|
297
|
+
semiBold: true,
|
298
|
+
center: true
|
299
|
+
)
|
300
|
+
.padding(.horizontal, 30)
|
301
|
+
Spacer()
|
302
|
+
}
|
303
|
+
} else {
|
304
|
+
ScrollView {
|
305
|
+
if let playbackList = tuya.playbackVideoList, !playbackList.isEmpty {
|
306
|
+
ForEach(0..<playbackList.count, id: \.self) { index in
|
307
|
+
VideoItem(
|
308
|
+
item: playbackList[index],
|
309
|
+
currentSliderValue: $currentSliderValue,
|
310
|
+
showSlider: showSlider
|
311
|
+
)
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
.background(LocalColor.Main.light)
|
316
|
+
}
|
317
|
+
}
|
318
|
+
.frame(maxWidth: .infinity)
|
319
|
+
.background(LocalColor.Main.light)
|
320
|
+
.alert(
|
321
|
+
isPresented: $tuya.isRecordingSuccess,
|
322
|
+
content: {
|
323
|
+
getSuccessAlert(
|
324
|
+
title: "A recording has been saved to your photo gallery."
|
325
|
+
)
|
326
|
+
})
|
327
|
+
}
|
328
|
+
}
|
329
|
+
|
330
|
+
struct VideoItem: View {
|
331
|
+
|
332
|
+
@ObservedObject var tuya = Tuya.shared
|
333
|
+
var item: [AnyHashable: Any]
|
334
|
+
@Binding var currentSliderValue: Double
|
335
|
+
var showSlider: () -> Void
|
336
|
+
|
337
|
+
var body: some View {
|
338
|
+
let isSelected = (tuya.selectedItem?["startTime"] as? Int) == (item["startTime"] as? Int)
|
339
|
+
|
340
|
+
HStack {
|
341
|
+
VStack(alignment: .leading, spacing: 5) {
|
342
|
+
Label(
|
343
|
+
title: "\(convertTimestampToTime(item["startTime"] as? Int))",
|
344
|
+
l: true,
|
345
|
+
primary: true,
|
346
|
+
bold: true,
|
347
|
+
left: true
|
348
|
+
)
|
349
|
+
|
350
|
+
Label(
|
351
|
+
title: ("Duration: \(calculateVideoDuration(from: item["startTime"] as? Int, to: item["endTime"] as? Int))"),
|
352
|
+
m: true,
|
353
|
+
secondary: true,
|
354
|
+
left: true
|
355
|
+
)
|
356
|
+
.padding(.top, 5)
|
357
|
+
}
|
358
|
+
.padding(15)
|
359
|
+
|
360
|
+
Spacer()
|
361
|
+
}
|
362
|
+
.frame(maxWidth: /*@START_MENU_TOKEN@*/.infinity/*@END_MENU_TOKEN@*/)
|
363
|
+
.background(isSelected ? LocalColor.Secondary.light : LocalColor.Monochrome.white)
|
364
|
+
.cornerRadius(5)
|
365
|
+
.padding(.top, 8)
|
366
|
+
.padding(.horizontal, 10)
|
367
|
+
.onTapGesture {
|
368
|
+
tuya.selectedItem = item
|
369
|
+
currentSliderValue = 0
|
370
|
+
startPlayback(
|
371
|
+
playTime: item["startTime"] as? Int,
|
372
|
+
startTime: item["startTime"] as? Int,
|
373
|
+
endTime: item["endTime"] as? Int
|
374
|
+
)
|
375
|
+
showSlider()
|
376
|
+
}
|
377
|
+
}
|
378
|
+
|
379
|
+
private func convertTimestampToTime(_ timestamp: Int?) -> String {
|
380
|
+
guard let timestamp = timestamp else { return "Invalid Time" }
|
381
|
+
let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
|
382
|
+
let formatter = DateFormatter()
|
383
|
+
formatter.dateFormat = "hh:mm a"
|
384
|
+
return formatter.string(from: date)
|
385
|
+
}
|
386
|
+
}
|
387
|
+
|
388
|
+
private func startPlayback(playTime: Int?, startTime: Int?, endTime: Int?) {
|
389
|
+
|
390
|
+
guard let startTime = startTime, let endTime = endTime, let playTime = playTime else {
|
391
|
+
print("Tuya: Invalid start/end/play time")
|
392
|
+
return
|
393
|
+
}
|
394
|
+
|
395
|
+
if Tuya.shared.isConnected {
|
396
|
+
Tuya.shared.startPlayback(
|
397
|
+
playTime: playTime,
|
398
|
+
startTime: startTime,
|
399
|
+
stopTime: endTime
|
400
|
+
)
|
401
|
+
} else {
|
402
|
+
Tuya.shared.isPlaybacking = false
|
403
|
+
print("Tuya: Camera is disconnected, hence unable to start the video")
|
404
|
+
}
|
405
|
+
}
|
406
|
+
|
407
|
+
func calculateVideoDuration(from startTime: Int?, to endTime: Int?) -> String {
|
408
|
+
guard let startTime = startTime, let endTime = endTime else { return "Invalid Duration" }
|
409
|
+
let durationInSeconds = TimeInterval(endTime - startTime)
|
410
|
+
let hours = Int(durationInSeconds) / 3600
|
411
|
+
let minutes = (Int(durationInSeconds) % 3600) / 60
|
412
|
+
let seconds = Int(durationInSeconds) % 60
|
413
|
+
|
414
|
+
return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
|
415
|
+
}
|
416
|
+
|
417
|
+
struct PlaybackBottomBar: View {
|
418
|
+
|
419
|
+
@ObservedObject var tuya = Tuya.shared
|
420
|
+
@Binding var currentSliderValue: Double
|
421
|
+
|
422
|
+
var body: some View {
|
423
|
+
HStack {
|
424
|
+
Spacer()
|
425
|
+
|
426
|
+
IconButton(
|
427
|
+
imageName: tuya.isPlaybackMuted ? "keyless_sound_off" : "keyless_sound_on",
|
428
|
+
event: tuya.isPlaybackMuted ? "Playback Speaker On" : "Playback Speaker Off",
|
429
|
+
size: tuya.isPlaybackMuted ? 28 : 40,
|
430
|
+
action: {
|
431
|
+
guard tuya.isConnected else {
|
432
|
+
print("Tuya: Camera not connected. Speaker action disabled.")
|
433
|
+
return
|
434
|
+
}
|
435
|
+
|
436
|
+
guard tuya.isPlaybacking else {
|
437
|
+
print("Tuya: Playback not started. Speaker action disabled.")
|
438
|
+
return
|
439
|
+
}
|
440
|
+
|
441
|
+
if (tuya.isPlaybackMuted) {
|
442
|
+
tuya.enableMute(enable: false, type: .playback)
|
443
|
+
} else {
|
444
|
+
tuya.enableMute(enable: true, type: .playback)
|
445
|
+
}
|
446
|
+
}
|
447
|
+
)
|
448
|
+
|
449
|
+
Spacer()
|
450
|
+
|
451
|
+
IconButton(
|
452
|
+
imageName: tuya.isRecording ? "keyless_record_on" : "keyless_record",
|
453
|
+
event: tuya.isRecording ? "Playback Recording Off" : "Playback Recording On",
|
454
|
+
size: tuya.isRecording ? 40 : 28,
|
455
|
+
action: {
|
456
|
+
guard tuya.isConnected else {
|
457
|
+
print("Tuya: Camera not connected. Start/Stop recording action disabled.")
|
458
|
+
return
|
459
|
+
}
|
460
|
+
|
461
|
+
guard tuya.isPlaybacking else {
|
462
|
+
print("Tuya: Playback not started. Start/Stop recording action disabled.")
|
463
|
+
return
|
464
|
+
}
|
465
|
+
|
466
|
+
tuya.isRecording ? tuya.stopRecording() : tuya.startRecording()
|
467
|
+
}
|
468
|
+
)
|
469
|
+
|
470
|
+
Spacer()
|
471
|
+
|
472
|
+
IconButton(
|
473
|
+
imageName: tuya.isPaused ? "keyless_play_playback" : "keyless_pause",
|
474
|
+
event: tuya.isPaused ? "Resume Playback" : "Pause Playback",
|
475
|
+
size: 45,
|
476
|
+
action: {
|
477
|
+
guard tuya.isConnected else {
|
478
|
+
print("Tuya: Camera not connected. Resume/Pause action disabled.")
|
479
|
+
return
|
480
|
+
}
|
481
|
+
|
482
|
+
guard tuya.isPlaybacking else {
|
483
|
+
print("Tuya: Playback is not started. Resume/Pause action disabled.")
|
484
|
+
return
|
485
|
+
}
|
486
|
+
|
487
|
+
if tuya.isPaused {
|
488
|
+
guard let selectedItem = tuya.selectedItem,
|
489
|
+
let startTime = selectedItem["startTime"] as? Int,
|
490
|
+
let endTime = selectedItem["endTime"] as? Int else { return }
|
491
|
+
|
492
|
+
let videoDuration = Double(endTime - startTime)
|
493
|
+
|
494
|
+
if currentSliderValue >= videoDuration {
|
495
|
+
// If playback is completed then Restart from the beginning
|
496
|
+
currentSliderValue = 0
|
497
|
+
tuya.startPlayback(
|
498
|
+
playTime: startTime,
|
499
|
+
startTime: startTime,
|
500
|
+
stopTime: endTime
|
501
|
+
)
|
502
|
+
} else {
|
503
|
+
tuya.resumePlayback()
|
504
|
+
}
|
505
|
+
|
506
|
+
} else {
|
507
|
+
tuya.pausePlayback()
|
508
|
+
}
|
509
|
+
}
|
510
|
+
)
|
511
|
+
|
512
|
+
Spacer()
|
513
|
+
|
514
|
+
IconButton(
|
515
|
+
imageName: "keyless_photo",
|
516
|
+
event: "Playback Screenshot",
|
517
|
+
size: 28,
|
518
|
+
action: {
|
519
|
+
guard tuya.isConnected else {
|
520
|
+
print("Tuya: Camera not connected. Screenshot action disabled.")
|
521
|
+
return
|
522
|
+
}
|
523
|
+
|
524
|
+
guard tuya.isPlaybacking else {
|
525
|
+
print("Tuya: Playback is not started. Screenshot action disabled.")
|
526
|
+
return
|
527
|
+
}
|
528
|
+
|
529
|
+
tuya.screenshot()
|
530
|
+
}
|
531
|
+
)
|
532
|
+
|
533
|
+
Spacer()
|
534
|
+
}
|
535
|
+
.padding(.top)
|
536
|
+
.padding(.horizontal)
|
537
|
+
.frame(height: 70)
|
538
|
+
.padding(.bottom, 15)
|
539
|
+
.background(LocalColor.Monochrome.grey)
|
540
|
+
.edgesIgnoringSafeArea(.horizontal)
|
541
|
+
}
|
542
|
+
}
|
543
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
import SwiftUI
|
2
|
+
import ThingSmartCameraBase
|
3
|
+
|
4
|
+
struct PreviewView: UIViewRepresentable {
|
5
|
+
|
6
|
+
class Coordinator: NSObject, UIScrollViewDelegate {
|
7
|
+
var scrollView: UIScrollView?
|
8
|
+
|
9
|
+
override init() {
|
10
|
+
super.init()
|
11
|
+
|
12
|
+
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
|
13
|
+
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)
|
14
|
+
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: OrientationManager.orientationDidChangeNotification, object: nil)
|
15
|
+
}
|
16
|
+
|
17
|
+
deinit {
|
18
|
+
UIDevice.current.endGeneratingDeviceOrientationNotifications()
|
19
|
+
NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
|
20
|
+
NotificationCenter.default.removeObserver(self, name: OrientationManager.orientationDidChangeNotification, object: nil)
|
21
|
+
}
|
22
|
+
|
23
|
+
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
|
24
|
+
return scrollView.subviews.first
|
25
|
+
}
|
26
|
+
|
27
|
+
func scrollViewDidZoom(_ scrollView: UIScrollView) {
|
28
|
+
guard let zoomView = scrollView.subviews.first else { return }
|
29
|
+
|
30
|
+
let offsetX = max((scrollView.bounds.size.width - zoomView.frame.size.width) * 0.5, 0)
|
31
|
+
let offsetY = max((scrollView.bounds.size.height - zoomView.frame.size.height) * 0.5, 0)
|
32
|
+
|
33
|
+
zoomView.center = CGPoint(x: scrollView.contentSize.width * 0.5 + offsetX,
|
34
|
+
y: scrollView.contentSize.height * 0.5 + offsetY)
|
35
|
+
}
|
36
|
+
|
37
|
+
func resetZoom() {
|
38
|
+
guard let scrollView = scrollView else { return }
|
39
|
+
scrollView.setZoomScale(1.0, animated: true)
|
40
|
+
scrollView.setContentOffset(CGPoint.zero, animated: true)
|
41
|
+
}
|
42
|
+
|
43
|
+
@objc func orientationChanged() {
|
44
|
+
resetZoom()
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
func makeUIView(context: Context) -> UIView {
|
49
|
+
let containerView = UIView()
|
50
|
+
let scrollView = UIScrollView()
|
51
|
+
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
52
|
+
scrollView.minimumZoomScale = 1.0
|
53
|
+
scrollView.maximumZoomScale = 4.0
|
54
|
+
scrollView.delegate = context.coordinator
|
55
|
+
scrollView.bounces = false
|
56
|
+
scrollView.showsVerticalScrollIndicator = false
|
57
|
+
scrollView.showsHorizontalScrollIndicator = false
|
58
|
+
scrollView.clipsToBounds = true
|
59
|
+
|
60
|
+
containerView.addSubview(scrollView)
|
61
|
+
|
62
|
+
|
63
|
+
NSLayoutConstraint.activate([
|
64
|
+
scrollView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
|
65
|
+
scrollView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
|
66
|
+
scrollView.topAnchor.constraint(equalTo: containerView.topAnchor),
|
67
|
+
scrollView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
|
68
|
+
])
|
69
|
+
|
70
|
+
if let videoView = Tuya.shared.cameraType?.videoView() {
|
71
|
+
videoView.contentMode = .scaleAspectFit
|
72
|
+
scrollView.addSubview(videoView)
|
73
|
+
videoView.translatesAutoresizingMaskIntoConstraints = false
|
74
|
+
|
75
|
+
NSLayoutConstraint.activate([
|
76
|
+
videoView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
|
77
|
+
videoView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor),
|
78
|
+
videoView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 1.0),
|
79
|
+
videoView.heightAnchor.constraint(equalTo: scrollView.heightAnchor, multiplier: 1.0)
|
80
|
+
])
|
81
|
+
} else {
|
82
|
+
print("Tuya: Video view is nil")
|
83
|
+
}
|
84
|
+
|
85
|
+
context.coordinator.scrollView = scrollView
|
86
|
+
context.coordinator.resetZoom()
|
87
|
+
return containerView
|
88
|
+
}
|
89
|
+
|
90
|
+
func updateUIView(_ uiView: UIView, context: Context) {
|
91
|
+
guard let scrollView = context.coordinator.scrollView else { return }
|
92
|
+
if let videoView = Tuya.shared.cameraType?.videoView() {
|
93
|
+
videoView.setNeedsDisplay()
|
94
|
+
context.coordinator.resetZoom()
|
95
|
+
} else {
|
96
|
+
print("Tuya: Video view is nil in updateUIView")
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
func makeCoordinator() -> Coordinator {
|
101
|
+
Coordinator()
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
func openLivePreview(appFlavor: String) {
|
106
|
+
|
107
|
+
DispatchQueue.main.async {
|
108
|
+
Themes.configureTheme(for: appFlavor)
|
109
|
+
let orientationManager = OrientationManager()
|
110
|
+
let dashboardView = NavigationController().environmentObject(orientationManager)
|
111
|
+
let hostingController = UIHostingController(rootView: dashboardView)
|
112
|
+
hostingController.modalPresentationStyle = .fullScreen
|
113
|
+
if let rootVC = UIApplication.shared.windows.first?.rootViewController {
|
114
|
+
rootVC.present(hostingController, animated: true, completion: nil)
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|