@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,40 @@
|
|
1
|
+
package com.rentlytuya.util
|
2
|
+
|
3
|
+
import android.content.Context
|
4
|
+
import android.util.Log
|
5
|
+
import com.loopj.android.airbrake.AirbrakeNotifier
|
6
|
+
import com.rentlytuya.tuya.Tuya.TAG
|
7
|
+
|
8
|
+
object Airbrake {
|
9
|
+
|
10
|
+
private var isInitialized = false
|
11
|
+
|
12
|
+
fun initialize(
|
13
|
+
airbrakeKey: String,
|
14
|
+
airbrakeID: String,
|
15
|
+
context: Context
|
16
|
+
) {
|
17
|
+
if (isInitialized) return
|
18
|
+
runCatching {
|
19
|
+
AirbrakeNotifier.register(context, airbrakeKey)
|
20
|
+
isInitialized = true
|
21
|
+
Log.i(TAG, "Successfully Initialized Airbrake")
|
22
|
+
}.onFailure {
|
23
|
+
Log.i(TAG, "Error in Airbrake Initialization")
|
24
|
+
it.printStackTrace()
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
fun logMessage(title: String, message: String, additionalInfo: Map<String, String>? = null) {
|
29
|
+
Log.i(TAG, "$title, $message, $additionalInfo")
|
30
|
+
if (!isInitialized) return
|
31
|
+
runCatching {
|
32
|
+
val logData = additionalInfo.orEmpty()
|
33
|
+
val throwable = Throwable("$title: $message")
|
34
|
+
AirbrakeNotifier.notify(throwable, logData)
|
35
|
+
}.onFailure {
|
36
|
+
Log.i(TAG, "Error in Airbrake log message")
|
37
|
+
it.printStackTrace()
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
@@ -0,0 +1,53 @@
|
|
1
|
+
package com.rentlytuya.util
|
2
|
+
|
3
|
+
object DPConstants {
|
4
|
+
|
5
|
+
const val PTZ_CONTROL: String = "119"
|
6
|
+
const val PTZ_STOP: String = "116"
|
7
|
+
|
8
|
+
const val BASIC_FLIP: String = "103"
|
9
|
+
const val WATERMARK: String = "104"
|
10
|
+
const val ANTI_DISMANTLING_ALARM: String = "231"
|
11
|
+
|
12
|
+
// 0-Auto, 1-Off, 2-On
|
13
|
+
const val BASIC_NIGHT_VISION: String = "108"
|
14
|
+
|
15
|
+
// 0-None, 1-Mechanical, 2-Digital, 3-No bells
|
16
|
+
const val CHIME_TYPE: String = "165"
|
17
|
+
|
18
|
+
// Motion Detection for 8s and AOSU Doorbell
|
19
|
+
const val MOTION_SWITCH: String = "134"
|
20
|
+
const val MOTION_SENSITIVITY: String = "106"
|
21
|
+
|
22
|
+
// Motion Sensitivity for AOSU
|
23
|
+
const val MOTION_SENSITIVITY_AOSU: String = "152"
|
24
|
+
|
25
|
+
// Motion Detection for 15s
|
26
|
+
const val PIR_SWITCH: String = "240"
|
27
|
+
const val PIR_SENSITIVITY: String = "241"
|
28
|
+
|
29
|
+
// 1-Normal, 2-Abnormal, 3-Insufficient Capacity, 4-Formatting.., 5-No Storage
|
30
|
+
const val SD_STATUS: String = "110"
|
31
|
+
const val SD_STORAGE: String = "109"
|
32
|
+
const val SD_FORMAT: String = "111"
|
33
|
+
const val SD_FORMAT_STATUS: String = "117"
|
34
|
+
const val SD_RECORD_SWITCH: String = "150"
|
35
|
+
const val SD_RECORD_MODE: String = "151"
|
36
|
+
|
37
|
+
const val WIRELESS_ELECTRICITY: String = "145"
|
38
|
+
|
39
|
+
// 0-Battery Powered, 1-Wire Mode
|
40
|
+
const val WIRELESS_POWER_MODE: String = "146"
|
41
|
+
|
42
|
+
// DP Data type
|
43
|
+
const val SCHEMA_TYPE_RAW: String = "raw"
|
44
|
+
const val SCHEMA_TYPE_BOOL: String = "bool"
|
45
|
+
const val SCHEMA_TYPE_ENUM: String = "enum"
|
46
|
+
const val SCHEMA_TYPE_VALUE: String = "value"
|
47
|
+
const val SCHEMA_TYPE_STRING: String = "string"
|
48
|
+
|
49
|
+
const val PTZ_UP: String = "0"
|
50
|
+
const val PTZ_LEFT: String = "2"
|
51
|
+
const val PTZ_DOWN: String = "4"
|
52
|
+
const val PTZ_RIGHT: String = "6"
|
53
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
package com.rentlytuya.util
|
2
|
+
|
3
|
+
import android.content.Context
|
4
|
+
import android.os.StatFs
|
5
|
+
import com.facebook.drawee.backends.pipeline.Fresco
|
6
|
+
import com.facebook.imagepipeline.core.ExecutorSupplier
|
7
|
+
import com.facebook.imagepipeline.core.ImagePipelineConfig
|
8
|
+
import com.facebook.imagepipeline.listener.RequestListener
|
9
|
+
import com.thingclips.imagepipeline.okhttp3.OkHttpImagePipelineConfigFactory
|
10
|
+
import com.thingclips.smart.android.common.task.ThingExecutor
|
11
|
+
import okhttp3.Cache
|
12
|
+
import okhttp3.OkHttpClient
|
13
|
+
import java.io.File
|
14
|
+
import java.util.concurrent.Executor
|
15
|
+
import java.util.concurrent.ScheduledExecutorService
|
16
|
+
import java.util.concurrent.TimeUnit
|
17
|
+
|
18
|
+
object FrescoManager {
|
19
|
+
|
20
|
+
@JvmStatic
|
21
|
+
fun initFresco(context: Context) {
|
22
|
+
val defaultConfig = getDefaultConfig(context)
|
23
|
+
initFresco(context, defaultConfig)
|
24
|
+
}
|
25
|
+
|
26
|
+
@JvmStatic
|
27
|
+
fun initFresco(context: Context, config: ImagePipelineConfig) {
|
28
|
+
Fresco.initialize(context, config)
|
29
|
+
}
|
30
|
+
|
31
|
+
private fun getDefaultConfig(context: Context): ImagePipelineConfig {
|
32
|
+
val requestListeners: Set<RequestListener> = emptySet()
|
33
|
+
val cacheDir = File(context.cacheDir, "okhttp3")
|
34
|
+
val size = calculateDiskCacheSize(cacheDir)
|
35
|
+
|
36
|
+
val okHttpClient = OkHttpClient.Builder()
|
37
|
+
.cache(Cache(cacheDir, size))
|
38
|
+
.connectTimeout(0, TimeUnit.MILLISECONDS)
|
39
|
+
.readTimeout(0, TimeUnit.MILLISECONDS)
|
40
|
+
.writeTimeout(0, TimeUnit.MILLISECONDS)
|
41
|
+
.build()
|
42
|
+
|
43
|
+
val builder = OkHttpImagePipelineConfigFactory.newBuilder(
|
44
|
+
context.applicationContext, okHttpClient
|
45
|
+
).setRequestListeners(requestListeners)
|
46
|
+
|
47
|
+
builder.setExecutorSupplier(object : ExecutorSupplier {
|
48
|
+
override fun forLocalStorageRead(): Executor =
|
49
|
+
ThingExecutor.getInstance().thingExecutorService
|
50
|
+
|
51
|
+
override fun forLocalStorageWrite(): Executor =
|
52
|
+
ThingExecutor.getInstance().thingExecutorService
|
53
|
+
|
54
|
+
override fun forDecode(): Executor = ThingExecutor.getInstance().thingExecutorService
|
55
|
+
|
56
|
+
override fun forBackgroundTasks(): Executor = ThingExecutor.getInstance().thingExecutorService
|
57
|
+
|
58
|
+
override fun forLightweightBackgroundTasks(): Executor =
|
59
|
+
ThingExecutor.getInstance().thingExecutorService
|
60
|
+
|
61
|
+
override fun forThumbnailProducer(): Executor =
|
62
|
+
ThingExecutor.getInstance().thingExecutorService
|
63
|
+
|
64
|
+
override fun scheduledExecutorServiceForBackgroundTasks(): ScheduledExecutorService? = null
|
65
|
+
})
|
66
|
+
|
67
|
+
return builder.build()
|
68
|
+
}
|
69
|
+
|
70
|
+
private const val MIN_DISK_CACHE_SIZE = 5 * 1024 * 1024L // 5MB
|
71
|
+
private const val MAX_DISK_CACHE_SIZE = 10 * 1024 * 1024L // 50MB
|
72
|
+
|
73
|
+
private fun calculateDiskCacheSize(dir: File): Long {
|
74
|
+
var size = MIN_DISK_CACHE_SIZE
|
75
|
+
|
76
|
+
try {
|
77
|
+
val statFs = StatFs(dir.absolutePath)
|
78
|
+
val available = statFs.blockCountLong * statFs.blockSizeLong
|
79
|
+
size = available / 50 // Target 2% of the total space.
|
80
|
+
} catch (ignored: IllegalArgumentException) {
|
81
|
+
}
|
82
|
+
|
83
|
+
// Bound inside min/max size for disk cache.
|
84
|
+
return size.coerceIn(MIN_DISK_CACHE_SIZE, MAX_DISK_CACHE_SIZE)
|
85
|
+
}
|
86
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
package com.rentlytuya.util
|
2
|
+
|
3
|
+
import android.util.Log
|
4
|
+
import com.heapanalytics.android.Heap
|
5
|
+
import com.rentlytuya.tuya.Tuya.TAG
|
6
|
+
|
7
|
+
object Heap {
|
8
|
+
|
9
|
+
fun trackEvent(eventName: String, properties: Map<String, String>? = null) {
|
10
|
+
try {
|
11
|
+
Heap.track(eventName, properties)
|
12
|
+
} catch (e: Exception) {
|
13
|
+
Log.e(TAG, "Error in Heap trackEvent: $eventName", e)
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
package com.rentlytuya.util
|
2
|
+
|
3
|
+
import android.util.Log
|
4
|
+
import com.facebook.react.ReactApplication
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
6
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
7
|
+
import com.facebook.react.bridge.ReactMethod
|
8
|
+
import com.facebook.react.bridge.WritableNativeArray
|
9
|
+
import com.facebook.react.module.annotations.ReactModule
|
10
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
11
|
+
import com.rentlytuya.tuya.Tuya.TAG
|
12
|
+
|
13
|
+
@ReactModule(name = "KeylessListener")
|
14
|
+
class KeylessModule(private val reactContext: ReactApplicationContext) :
|
15
|
+
ReactContextBaseJavaModule(reactContext) {
|
16
|
+
|
17
|
+
private var eventEmitter: DeviceEventManagerModule.RCTDeviceEventEmitter? = null
|
18
|
+
private var onSuccessListener: ((String) -> Unit)? = null
|
19
|
+
private var onFailureListener: ((String) -> Unit)? = null
|
20
|
+
|
21
|
+
override fun getName(): String = "KeylessListener"
|
22
|
+
|
23
|
+
override fun initialize() {
|
24
|
+
super.initialize()
|
25
|
+
eventEmitter =
|
26
|
+
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
27
|
+
}
|
28
|
+
|
29
|
+
fun sendDataToJS(
|
30
|
+
eventName: String,
|
31
|
+
deviceId: String,
|
32
|
+
onSuccess: (String) -> Unit,
|
33
|
+
onFailure: (String) -> Unit
|
34
|
+
) {
|
35
|
+
try {
|
36
|
+
val params = WritableNativeArray()
|
37
|
+
params.pushString(deviceId) // For Update Default Settings value, id is passed
|
38
|
+
|
39
|
+
onSuccessListener = onSuccess
|
40
|
+
onFailureListener = onFailure
|
41
|
+
invokeJSMethod(methodName = eventName, params = params)
|
42
|
+
} catch (e: Exception) {
|
43
|
+
Log.e(TAG, "Error sending event to JS: ${e.message}", e)
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
private fun invokeJSMethod(methodName: String, params: WritableNativeArray) {
|
48
|
+
try {
|
49
|
+
val reactInstanceManager = (reactContext.applicationContext as ReactApplication)
|
50
|
+
.reactNativeHost.reactInstanceManager
|
51
|
+
|
52
|
+
val currentReactContext = reactInstanceManager.currentReactContext
|
53
|
+
if (currentReactContext == null || !currentReactContext.hasActiveCatalystInstance()) {
|
54
|
+
Log.e(TAG, "ReactContext is not active or null. Attempting to recreate")
|
55
|
+
reactInstanceManager.recreateReactContextInBackground()
|
56
|
+
Thread.sleep(2000)
|
57
|
+
}
|
58
|
+
|
59
|
+
if (currentReactContext != null) {
|
60
|
+
val catalystInstance = currentReactContext.catalystInstance
|
61
|
+
catalystInstance?.callFunction("RNOperation", methodName, params)
|
62
|
+
?: Log.e(TAG, "Catalyst instance is null")
|
63
|
+
}
|
64
|
+
|
65
|
+
} catch (e: Exception) {
|
66
|
+
Log.e(TAG, "Error invoking JS method: ${e.message}", e)
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
@ReactMethod
|
71
|
+
fun successCallback(message: String) {
|
72
|
+
onSuccessListener?.invoke(message)
|
73
|
+
onSuccessListener = null
|
74
|
+
}
|
75
|
+
|
76
|
+
@ReactMethod
|
77
|
+
fun failureCallback(message: String) {
|
78
|
+
onFailureListener?.invoke(message)
|
79
|
+
onFailureListener = null
|
80
|
+
}
|
81
|
+
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
package com.rentlytuya.util
|
2
|
+
|
3
|
+
import android.app.Activity
|
4
|
+
import android.content.Context
|
5
|
+
import android.content.Intent
|
6
|
+
import android.content.pm.PackageManager
|
7
|
+
import android.net.Uri
|
8
|
+
import android.provider.Settings
|
9
|
+
import androidx.core.app.ActivityCompat
|
10
|
+
import androidx.core.content.ContextCompat
|
11
|
+
|
12
|
+
object PermissionHandler {
|
13
|
+
|
14
|
+
fun isPermissionGranted(context: Context, permission: String): Boolean {
|
15
|
+
return ContextCompat.checkSelfPermission(
|
16
|
+
context,
|
17
|
+
permission
|
18
|
+
) == PackageManager.PERMISSION_GRANTED
|
19
|
+
}
|
20
|
+
|
21
|
+
fun arePermissionsGranted(context: Context, permissions: Array<String>): Boolean {
|
22
|
+
return permissions.all { permission ->
|
23
|
+
ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
fun checkAndRequestPermissions(
|
28
|
+
activity: Activity,
|
29
|
+
permissions: Array<String>,
|
30
|
+
requestCode: Int
|
31
|
+
): Boolean {
|
32
|
+
try {
|
33
|
+
val notGrantedPermissions = permissions.filter { permission ->
|
34
|
+
ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED
|
35
|
+
}
|
36
|
+
|
37
|
+
return if (notGrantedPermissions.isNotEmpty()) {
|
38
|
+
val shouldShowRationale = notGrantedPermissions.any { permission ->
|
39
|
+
ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)
|
40
|
+
}
|
41
|
+
|
42
|
+
if (!shouldShowRationale) {
|
43
|
+
ActivityCompat.requestPermissions(
|
44
|
+
activity,
|
45
|
+
notGrantedPermissions.toTypedArray(),
|
46
|
+
requestCode
|
47
|
+
)
|
48
|
+
} else {
|
49
|
+
openAppSettings(activity)
|
50
|
+
}
|
51
|
+
false
|
52
|
+
} else {
|
53
|
+
true
|
54
|
+
}
|
55
|
+
} catch (e: Exception) {
|
56
|
+
e.printStackTrace()
|
57
|
+
return false
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
fun requestPermission(activity: Activity, permission: String, requestCode: Int) {
|
62
|
+
try {
|
63
|
+
ActivityCompat.requestPermissions(activity, arrayOf(permission), requestCode)
|
64
|
+
} catch (e: Exception) {
|
65
|
+
e.printStackTrace()
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
private fun openAppSettings(activity: Activity) {
|
70
|
+
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
71
|
+
data = Uri.fromParts("package", activity.packageName, null)
|
72
|
+
}
|
73
|
+
activity.startActivity(intent)
|
74
|
+
}
|
75
|
+
}
|
@@ -0,0 +1,152 @@
|
|
1
|
+
package com.rentlytuya.util
|
2
|
+
|
3
|
+
import android.text.TextUtils
|
4
|
+
import com.alibaba.fastjson.JSON
|
5
|
+
import com.alibaba.fastjson.JSONArray
|
6
|
+
import com.alibaba.fastjson.JSONObject
|
7
|
+
import com.facebook.react.bridge.Arguments
|
8
|
+
import com.facebook.react.bridge.ReadableArray
|
9
|
+
import com.facebook.react.bridge.ReadableMap
|
10
|
+
import com.facebook.react.bridge.ReadableType
|
11
|
+
import com.facebook.react.bridge.WritableArray
|
12
|
+
import com.facebook.react.bridge.WritableMap
|
13
|
+
import java.math.BigDecimal
|
14
|
+
|
15
|
+
fun ReadableMap.checkParams(vararg keys: String): Boolean {
|
16
|
+
for (key in keys) {
|
17
|
+
if (!hasKey(key)) {
|
18
|
+
return false
|
19
|
+
}
|
20
|
+
}
|
21
|
+
return true
|
22
|
+
}
|
23
|
+
|
24
|
+
object ReactUtils {
|
25
|
+
|
26
|
+
private fun parseToMap(readableMap: ReadableMap): HashMap<String, Any?> {
|
27
|
+
val iterator = readableMap.keySetIterator()
|
28
|
+
val deconstructedMap = HashMap<String, Any?>()
|
29
|
+
while (iterator.hasNextKey()) {
|
30
|
+
val key = iterator.nextKey()
|
31
|
+
val type = readableMap.getType(key)
|
32
|
+
when (type) {
|
33
|
+
ReadableType.Null -> deconstructedMap[key] = null
|
34
|
+
ReadableType.Boolean -> deconstructedMap[key] = readableMap.getBoolean(key)
|
35
|
+
ReadableType.Number -> {
|
36
|
+
val value = readableMap.getDouble(key)
|
37
|
+
deconstructedMap[key] = if (value > Integer.MAX_VALUE && value % 1 == 0.0) {
|
38
|
+
value.toLong()
|
39
|
+
} else {
|
40
|
+
value
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
ReadableType.String -> deconstructedMap[key] = readableMap.getString(key)
|
45
|
+
ReadableType.Map -> deconstructedMap[key] = parseToMap(readableMap.getMap(key)!!)
|
46
|
+
ReadableType.Array -> deconstructedMap[key] = parseToList(readableMap.getArray(key)!!)
|
47
|
+
}
|
48
|
+
}
|
49
|
+
return deconstructedMap
|
50
|
+
}
|
51
|
+
|
52
|
+
fun parseToLongMap(readableMap: ReadableMap): HashMap<String, Any?> {
|
53
|
+
val iterator = readableMap.keySetIterator()
|
54
|
+
val deconstructedMap = HashMap<String, Any?>()
|
55
|
+
while (iterator.hasNextKey()) {
|
56
|
+
val key = iterator.nextKey()
|
57
|
+
val type = readableMap.getType(key)
|
58
|
+
when (type) {
|
59
|
+
ReadableType.Null -> deconstructedMap[key] = null
|
60
|
+
ReadableType.Boolean -> deconstructedMap[key] = readableMap.getBoolean(key)
|
61
|
+
ReadableType.Number -> {
|
62
|
+
val value = readableMap.getDouble(key)
|
63
|
+
deconstructedMap[key] = try {
|
64
|
+
if (value > Integer.MAX_VALUE && value % 1 == 0.0) {
|
65
|
+
value.toLong()
|
66
|
+
} else {
|
67
|
+
value.toLong()
|
68
|
+
}
|
69
|
+
} catch (e: Exception) {
|
70
|
+
value
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
ReadableType.String -> deconstructedMap[key] = readableMap.getString(key)
|
75
|
+
ReadableType.Map -> deconstructedMap[key] = parseToMap(readableMap.getMap(key)!!)
|
76
|
+
ReadableType.Array -> deconstructedMap[key] = parseToList(readableMap.getArray(key)!!)
|
77
|
+
}
|
78
|
+
}
|
79
|
+
return deconstructedMap
|
80
|
+
}
|
81
|
+
|
82
|
+
private fun parseToList(readableArray: ReadableArray): ArrayList<Any?> {
|
83
|
+
val deconstructedList = ArrayList<Any?>(readableArray.size())
|
84
|
+
for (i in 0 until readableArray.size()) {
|
85
|
+
val indexType = readableArray.getType(i)
|
86
|
+
when (indexType) {
|
87
|
+
ReadableType.Null -> deconstructedList.add(i, null)
|
88
|
+
ReadableType.Boolean -> deconstructedList.add(i, readableArray.getBoolean(i))
|
89
|
+
ReadableType.Number -> {
|
90
|
+
val value = readableArray.getDouble(i)
|
91
|
+
deconstructedList.add(
|
92
|
+
i,
|
93
|
+
if (value > Integer.MAX_VALUE && value % 1 == 0.0) value.toLong() else value
|
94
|
+
)
|
95
|
+
}
|
96
|
+
|
97
|
+
ReadableType.String -> deconstructedList.add(i, readableArray.getString(i))
|
98
|
+
ReadableType.Map -> deconstructedList.add(i, parseToMap(readableArray.getMap(i)))
|
99
|
+
ReadableType.Array -> deconstructedList.add(i, parseToList(readableArray.getArray(i)))
|
100
|
+
}
|
101
|
+
}
|
102
|
+
return deconstructedList
|
103
|
+
}
|
104
|
+
|
105
|
+
private fun parseToWritableMap(s: String): WritableMap {
|
106
|
+
return if (TextUtils.isEmpty(s)) Arguments.createMap() else parseToWritableMap(
|
107
|
+
JSON.parseObject(
|
108
|
+
s
|
109
|
+
)
|
110
|
+
)
|
111
|
+
}
|
112
|
+
|
113
|
+
fun parseToWritableMap(data: Any?): WritableMap {
|
114
|
+
return if (data == null) Arguments.createMap() else parseToWritableMap(JSON.toJSONString(data))
|
115
|
+
}
|
116
|
+
|
117
|
+
private fun parseToWritableMap(json: JSONObject): WritableMap {
|
118
|
+
val map = Arguments.createMap()
|
119
|
+
for ((key, obv) in json.entries) {
|
120
|
+
when (obv) {
|
121
|
+
is JSONObject -> map.putMap(key, parseToWritableMap(obv))
|
122
|
+
is JSONArray -> map.putArray(key, parseToWritableArray(obv))
|
123
|
+
is Int -> map.putInt(key, obv)
|
124
|
+
is String -> map.putString(key, obv)
|
125
|
+
is Boolean -> map.putBoolean(key, obv)
|
126
|
+
is Double -> map.putDouble(key, obv)
|
127
|
+
is BigDecimal -> map.putDouble(key, obv.toDouble())
|
128
|
+
is Long -> map.putString(key, obv.toString())
|
129
|
+
else -> map.putNull(key)
|
130
|
+
}
|
131
|
+
}
|
132
|
+
return map
|
133
|
+
}
|
134
|
+
|
135
|
+
private fun parseToWritableArray(jsonArray: JSONArray): WritableArray {
|
136
|
+
val list = Arguments.createArray()
|
137
|
+
for (obv in jsonArray.toTypedArray()) {
|
138
|
+
when (obv) {
|
139
|
+
is JSONObject -> list.pushMap(parseToWritableMap(obv))
|
140
|
+
is JSONArray -> list.pushArray(parseToWritableArray(obv))
|
141
|
+
is Int -> list.pushInt(obv)
|
142
|
+
is String -> list.pushString(obv)
|
143
|
+
is Boolean -> list.pushBoolean(obv)
|
144
|
+
is Double -> list.pushDouble(obv)
|
145
|
+
is BigDecimal -> list.pushDouble(obv.toDouble())
|
146
|
+
is Long -> list.pushString(obv.toString())
|
147
|
+
else -> list.pushNull()
|
148
|
+
}
|
149
|
+
}
|
150
|
+
return list
|
151
|
+
}
|
152
|
+
}
|
@@ -0,0 +1,128 @@
|
|
1
|
+
package com.rentlytuya.util
|
2
|
+
|
3
|
+
import android.content.res.Configuration
|
4
|
+
import android.os.Build
|
5
|
+
import androidx.annotation.RequiresApi
|
6
|
+
import androidx.compose.runtime.Composable
|
7
|
+
import androidx.compose.ui.res.stringResource
|
8
|
+
import java.text.SimpleDateFormat
|
9
|
+
import java.time.Instant
|
10
|
+
import java.time.LocalDateTime
|
11
|
+
import java.time.ZoneId
|
12
|
+
import java.time.ZoneOffset
|
13
|
+
import java.time.format.DateTimeFormatter
|
14
|
+
import java.util.Calendar
|
15
|
+
import java.util.Date
|
16
|
+
import java.util.Locale
|
17
|
+
import java.util.concurrent.TimeUnit
|
18
|
+
import kotlin.contracts.ExperimentalContracts
|
19
|
+
import kotlin.contracts.contract
|
20
|
+
|
21
|
+
object Util {
|
22
|
+
@Composable
|
23
|
+
fun strings(id: Int): String =
|
24
|
+
stringResource(id = id)
|
25
|
+
|
26
|
+
fun isLandscape(config: Configuration): Boolean =
|
27
|
+
config.orientation == Configuration.ORIENTATION_LANDSCAPE
|
28
|
+
}
|
29
|
+
|
30
|
+
object DateUtil {
|
31
|
+
|
32
|
+
fun getCurrentTimeInSeconds(): Long {
|
33
|
+
return System.currentTimeMillis() / 1000
|
34
|
+
}
|
35
|
+
|
36
|
+
fun getDateMinusYearsInSeconds(years: Int): Long {
|
37
|
+
val calendar = Calendar.getInstance()
|
38
|
+
calendar.add(Calendar.YEAR, -years)
|
39
|
+
|
40
|
+
return calendar.timeInMillis / 1000
|
41
|
+
}
|
42
|
+
|
43
|
+
fun getDateComponents(dateLong: Long): Triple<Int, Int, Int> {
|
44
|
+
val calendar = Calendar.getInstance().apply {
|
45
|
+
timeInMillis = dateLong
|
46
|
+
}
|
47
|
+
|
48
|
+
val year = calendar.get(Calendar.YEAR)
|
49
|
+
val month = calendar.get(Calendar.MONTH) + 1
|
50
|
+
val day = calendar.get(Calendar.DAY_OF_MONTH)
|
51
|
+
|
52
|
+
return Triple(year, month, day)
|
53
|
+
}
|
54
|
+
|
55
|
+
fun convertTimestampToTime(timestamp: Int, format: String = "hh:mm a"): String {
|
56
|
+
val date = Date(timestamp * 1000L)
|
57
|
+
val formatter = SimpleDateFormat(format, Locale.getDefault())
|
58
|
+
return formatter.format(date)
|
59
|
+
}
|
60
|
+
|
61
|
+
fun formatSecondsToHHMMSS(seconds: Int): String {
|
62
|
+
val hours = seconds / 3600
|
63
|
+
val minutes = (seconds % 3600) / 60
|
64
|
+
val secs = seconds % 60
|
65
|
+
|
66
|
+
return String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes, secs)
|
67
|
+
}
|
68
|
+
|
69
|
+
fun calculateDuration(startTime: Int, endTime: Int): String {
|
70
|
+
val diffInSeconds = endTime - startTime
|
71
|
+
|
72
|
+
val hours = TimeUnit.SECONDS.toHours(diffInSeconds.toLong())
|
73
|
+
val minutes = TimeUnit.SECONDS.toMinutes(diffInSeconds.toLong()) % 60
|
74
|
+
val seconds = diffInSeconds % 60
|
75
|
+
|
76
|
+
return String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes, seconds)
|
77
|
+
}
|
78
|
+
|
79
|
+
fun calculateSecondsBetweenTimestamps(startTime: Int, endTime: Int): Long {
|
80
|
+
return (endTime - startTime).toLong()
|
81
|
+
}
|
82
|
+
|
83
|
+
fun incrementTimestampBySeconds(timestamp: Int, secondsToAdd: Int): Int {
|
84
|
+
return timestamp + secondsToAdd
|
85
|
+
}
|
86
|
+
|
87
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
88
|
+
fun getStartOfDay(epochMillis: Long): Long {
|
89
|
+
return Instant.ofEpochMilli(epochMillis)
|
90
|
+
.atZone(ZoneId.systemDefault())
|
91
|
+
.toLocalDate()
|
92
|
+
.atStartOfDay(ZoneId.systemDefault())
|
93
|
+
.toInstant()
|
94
|
+
.toEpochMilli()
|
95
|
+
}
|
96
|
+
|
97
|
+
@RequiresApi(Build.VERSION_CODES.O)
|
98
|
+
fun convertToEpoch(isoDateString: String): Long {
|
99
|
+
return try {
|
100
|
+
val instant = Instant.from(DateTimeFormatter.ISO_INSTANT.parse(isoDateString))
|
101
|
+
instant.epochSecond
|
102
|
+
} catch (e: Exception) {
|
103
|
+
e.printStackTrace()
|
104
|
+
val oneYearBack = LocalDateTime.now().minusYears(1).toEpochSecond(ZoneOffset.UTC)
|
105
|
+
oneYearBack
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
@OptIn(ExperimentalContracts::class)
|
110
|
+
inline fun <reified T> T?.isNull(): Boolean {
|
111
|
+
contract {
|
112
|
+
returns(true) implies (this@isNull == null)
|
113
|
+
}
|
114
|
+
return this == null
|
115
|
+
}
|
116
|
+
|
117
|
+
@OptIn(ExperimentalContracts::class)
|
118
|
+
inline fun <reified T> T?.isNotNull(): Boolean {
|
119
|
+
contract {
|
120
|
+
returns(true) implies (this@isNotNull != null)
|
121
|
+
}
|
122
|
+
return this != null
|
123
|
+
}
|
124
|
+
|
125
|
+
fun Boolean?.isTrue(): Boolean {
|
126
|
+
return this == true
|
127
|
+
}
|
128
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
2
|
+
android:width="24dp"
|
3
|
+
android:height="24dp"
|
4
|
+
android:tint="#FFFFFF"
|
5
|
+
android:viewportWidth="24"
|
6
|
+
android:viewportHeight="24">
|
7
|
+
|
8
|
+
<path
|
9
|
+
android:fillColor="@android:color/white"
|
10
|
+
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
|
11
|
+
|
12
|
+
</vector>
|