entry : entrySet()) {
+ sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue()));
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/FastBleLib/src/main/java/com/clj/fastble/utils/HexUtil.java b/FastBleLib/src/main/java/com/clj/fastble/utils/HexUtil.java
new file mode 100644
index 0000000..b4cd41c
--- /dev/null
+++ b/FastBleLib/src/main/java/com/clj/fastble/utils/HexUtil.java
@@ -0,0 +1,121 @@
+package com.clj.fastble.utils;
+
+public class HexUtil {
+
+ private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',
+ '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+ private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
+ '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ public static char[] encodeHex(byte[] data) {
+ return encodeHex(data, true);
+ }
+
+ public static char[] encodeHex(byte[] data, boolean toLowerCase) {
+ return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+ }
+
+ protected static char[] encodeHex(byte[] data, char[] toDigits) {
+ if (data == null)
+ return null;
+ int l = data.length;
+ char[] out = new char[l << 1];
+ for (int i = 0, j = 0; i < l; i++) {
+ out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
+ out[j++] = toDigits[0x0F & data[i]];
+ }
+ return out;
+ }
+
+
+ public static String encodeHexStr(byte[] data) {
+ return encodeHexStr(data, true);
+ }
+
+ public static String encodeHexStr(byte[] data, boolean toLowerCase) {
+ return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+ }
+
+
+ protected static String encodeHexStr(byte[] data, char[] toDigits) {
+ return new String(encodeHex(data, toDigits));
+ }
+
+ public static String formatHexString(byte[] data) {
+ return formatHexString(data, false);
+ }
+
+ public static String formatHexString(byte[] data, boolean addSpace) {
+ if (data == null || data.length < 1)
+ return null;
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < data.length; i++) {
+ String hex = Integer.toHexString(data[i] & 0xFF);
+ if (hex.length() == 1) {
+ hex = '0' + hex;
+ }
+ sb.append(hex);
+ if (addSpace)
+ sb.append(" ");
+ }
+ return sb.toString().trim();
+ }
+
+ public static byte[] decodeHex(char[] data) {
+ int len = data.length;
+
+ if ((len & 0x01) != 0) {
+ throw new RuntimeException("Odd number of characters.");
+ }
+
+ byte[] out = new byte[len >> 1];
+
+ // two characters form the hex value.
+ for (int i = 0, j = 0; j < len; i++) {
+ int f = toDigit(data[j], j) << 4;
+ j++;
+ f = f | toDigit(data[j], j);
+ j++;
+ out[i] = (byte) (f & 0xFF);
+ }
+
+ return out;
+ }
+
+
+ protected static int toDigit(char ch, int index) {
+ int digit = Character.digit(ch, 16);
+ if (digit == -1) {
+ throw new RuntimeException("Illegal hexadecimal character " + ch
+ + " at index " + index);
+ }
+ return digit;
+ }
+
+
+ public static byte[] hexStringToBytes(String hexString) {
+ if (hexString == null || hexString.equals("")) {
+ return null;
+ }
+ hexString = hexString.trim();
+ hexString = hexString.toUpperCase();
+ int length = hexString.length() / 2;
+ char[] hexChars = hexString.toCharArray();
+ byte[] d = new byte[length];
+ for (int i = 0; i < length; i++) {
+ int pos = i * 2;
+ d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
+ }
+ return d;
+ }
+
+ public static byte charToByte(char c) {
+ return (byte) "0123456789ABCDEF".indexOf(c);
+ }
+
+ public static String extractData(byte[] data, int position) {
+ return HexUtil.formatHexString(new byte[]{data[position]});
+ }
+
+}
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/agconnect-services.json b/app/agconnect-services.json
new file mode 100644
index 0000000..e69de29
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..25b99c4
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,335 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+ id 'kotlin-parcelize'
+ id 'dagger.hilt.android.plugin'
+ //极光推送start
+// id 'com.google.gms.google-services'
+// id 'com.huawei.agconnect'
+ //极光推送end
+}
+
+// Read values from gradle.properties or system environment variable(从gradle.properties里读取值)
+def getStripeReleaseKey() {
+ return findProperty('STRIPE_RELEASE_KEY') ?: ""
+}
+
+def getKey(def key) {
+ return findProperty(key) ?: ""
+}
+
+android {
+
+ compileSdkVersion 35
+// buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ applicationId "com.abbidot.tracker"
+ minSdkVersion 23
+ targetSdkVersion 35
+ versionCode 2020
+// versionName "2.0.20"
+ versionName "2.0.20-Beta2"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ ndk {
+ //选择要添加的对应 cpu 类型的 .so 库。
+ abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
+ }
+
+ manifestPlaceholders = [
+ GOOGLE_MAP_KEY : getKey("GOOGLE_MAP_KEY"),
+ BAIDU_MAP_KEY : getKey("BAIDU_MAP_KEY"),
+ STRIPE_RELEASE_KEY : getStripeReleaseKey(),
+ STRIPE_TEST_KEY : getKey("STRIPE_TEST_KEY"),
+ BUGLY_KEY : getKey("BUGLY_KEY"),
+ MAPBOX_ACCESS_TOKEN: getKey("MAPBOX_ACCESS_TOKEN"),
+ HTTP_REQUEST_KEY : getKey("HTTP_REQUEST_KEY"),
+
+ JPUSH_PKGNAME : "${applicationId}",
+ JPUSH_APPKEY : "c968a96f76fc4f52e0f764ee", //JPush 上注册的包名对应的 Appkey.
+ JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.
+// MEIZU_APPKEY : "MZ-魅族的APPKEY",
+// MEIZU_APPID : "MZ-魅族的APPID",
+// XIAOMI_APPID : "MI-小米的APPID",
+// XIAOMI_APPKEY : "MI-小米的APPKEY",
+// OPPO_APPKEY : "OP-oppo的APPKEY",
+// OPPO_APPID : "OP-oppo的APPID",
+// OPPO_APPSECRET: "OP-oppo的APPSECRET",
+// VIVO_APPKEY : "vivo的APPKEY",
+// VIVO_APPID : "vivo的APPID"
+ ]
+ }
+
+ // 读取local.properties文件
+ Properties properties = new Properties()
+ InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream()
+ properties.load(inputStream)
+ // 读取签名文件
+ def keyKeyStoreFile = file(properties.getProperty('keyStoreFile'))
+ // 读取签名文件别名、密码等信息
+ def keyKeyStorePassword = properties.getProperty('keyStorePassword')
+ def keyKeyAlias = properties.getProperty('keyAlias')
+ def keyKeyAliasPassword = properties.getProperty('keyAliasPassword')
+ signingConfigs {
+ release {
+ storeFile keyKeyStoreFile
+ storePassword keyKeyStorePassword
+ keyAlias keyKeyAlias
+ keyPassword keyKeyAliasPassword
+ }
+ debug {
+ storeFile keyKeyStoreFile
+ storePassword keyKeyStorePassword
+ keyAlias keyKeyAlias
+ keyPassword keyKeyAliasPassword
+ }
+ }
+ buildTypes {
+// release {
+// minifyEnabled false
+// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+// }
+ debug {
+// multiDexKeepProguard file('multidex-config.pro')
+ debuggable true
+ jniDebuggable true
+ // 移除无用的资源文件
+ shrinkResources false
+ // ZipAlign 优化
+ zipAlignEnabled false
+ // 设置混淆
+ minifyEnabled false
+ signingConfig signingConfigs.debug
+ }
+
+ release {
+// multiDexKeepProguard file('multidex-config.pro')
+ debuggable false
+ jniDebuggable false
+ // 移除无用的资源文件
+ shrinkResources false
+ // ZipAlign 优化
+ zipAlignEnabled true
+ // 设置混淆
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ signingConfig signingConfigs.release
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = '17'
+ }
+
+ applicationVariants.all { variant ->
+
+ // Apk 输出文件名配置
+ variant.outputs.all { output ->
+ outputFileName = 'Tracker_V' + variant.versionName + '_' + new Date().format('yyyyMMddhhmmss') + '_' + variant.buildType.name
+// if (variant.buildType.name == buildTypes.release.getName()) {
+// outputFileName += '_' + new Date().format('yyyyMMddhhmmss') + '_' + variant.buildType.name
+// }
+ outputFileName += '.apk'
+ }
+ }
+
+ viewBinding {
+ enabled = true
+ }
+ lint {
+ abortOnError false
+ checkReleaseBuilds false
+ }
+ namespace 'com.abbidot.tracker'
+ buildFeatures {
+ viewBinding true
+ buildConfig = true
+ }
+
+ //减少apk包的体积
+ packagingOptions {
+ //压缩动态库(对应iniLibs的配置)
+ jniLibs {
+ useLegacyPackaging = true
+ }
+ //压缩dex(对应dex的配置)
+ dex {
+ useLegacyPackaging = true
+ }
+ }
+}
+
+dependencies {
+ // 基类库
+ implementation project(':baselibrary')
+ implementation project(':easyPhotos')
+ //蓝牙架包https://github.com/Jasonchenlijian/FastBle
+// implementation 'com.github.Jasonchenlijian:FastBle:2.4.0'
+ implementation project(':FastBleLib')
+ //轻量级的Android端Socket框架https://github.com/jiusetian/EasySocket
+ implementation project(':easysocket')
+
+// implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+// implementation 'androidx.appcompat:appcompat:1.7.0'
+// implementation 'com.google.android.material:material:1.10.0'
+// implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.2.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
+
+ // Android官方库
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.arch.core:core-common:2.2.0'
+ implementation 'androidx.arch.core:core-runtime:2.2.0'
+ implementation 'androidx.activity:activity-ktx:1.9.3'
+ implementation 'androidx.fragment:fragment-ktx:1.5.6'
+ implementation 'androidx.annotation:annotation:1.9.1'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.7'
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.8.7'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7'
+
+ implementation 'androidx.room:room-runtime:2.5.2'
+// implementation 'androidx.room:room-rxjava2:2.3.0'
+ implementation 'androidx.room:room-ktx:2.5.2'
+ kapt 'androidx.room:room-compiler:2.5.2'
+ //hilt依赖注入https://mvnrepository.com/artifact/com.google.dagger/hilt-android-gradle-plugin
+ implementation "com.google.dagger:hilt-android:2.57"
+ kapt "com.google.dagger:hilt-android-compiler:2.57"
+
+ //Android UI 开发效率的 UI 库https://github.com/Tencent/QMUI_Android
+ implementation 'com.qmuiteam:qmui:2.1.0'
+ implementation 'com.qmuiteam:arch:2.1.0'
+ kapt 'com.qmuiteam:arch-compiler:2.1.0'
+
+ // 协程
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2'
+
+ // 图片框架 https://github.com/coil-kt/coil/blob/main/README-zh.md
+ implementation "io.coil-kt:coil:1.4.0"
+ //选择添加
+ implementation "io.coil-kt:coil-gif:1.4.0"//支持GIF
+
+ //lottie动画https://github.com/airbnb/lottie-android
+ implementation 'com.airbnb.android:lottie:6.6.7'
+ //https://github.com/CymChad/BaseRecyclerViewAdapterHelper
+ implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.11'
+ //升级recyclerview,因BaseRecyclerViewAdapterHelper item点击事件是使用1.2.0
+ implementation 'androidx.recyclerview:recyclerview:1.3.1'
+
+ //谷歌地图
+ implementation 'com.google.android.gms:play-services-maps:19.2.0'
+ //地图操作工具类,添加标记等https://github.com/googlemaps/android-maps-utils
+// implementation 'com.google.maps.android:android-maps-utils:2.3.0'
+// implementation 'com.google.maps.android:maps-utils-ktx:3.2.1'
+ //谷歌地图places
+// implementation 'com.google.android.libraries.places:places:2.5.0'
+ //连接谷歌服务定位,登录谷歌
+// implementation 'com.google.android.gms:play-services-auth:19.2.0'
+ //定位
+ implementation 'com.google.android.gms:play-services-location:21.3.0'
+
+ //动画https://github.com/daimajia/AndroidViewAnimations
+ implementation 'com.daimajia.androidanimations:library:2.4@aar'
+
+ //mapbox地图https://github.com/mapbox/mapbox-maps-android
+// implementation 'com.mapbox.maps:android:10.2.0'
+ //https://github.com/mapbox/mapbox-search-android
+ //用mapbox搜索SDK,地理编码 有搜索ui组件,已包括mapbox-search-android架包
+ implementation "com.mapbox.search:mapbox-search-android-ui:2.5.1"
+// mapbox搜索SDK,地理编码 没有搜索ui组件
+// implementation "com.mapbox.search:mapbox-search-android:1.0.0-beta.25"
+ //用于计算距离https://docs.mapbox.com/android/java/guides/turf/#available-methods
+ implementation 'com.mapbox.mapboxsdk:mapbox-sdk-turf:6.15.0'
+ //用于计算路线规划信息https://docs.mapbox.com/android/java/examples/dashed-directions-line/
+ implementation 'com.mapbox.mapboxsdk:mapbox-sdk-services:6.3.0'
+
+ // 权限请求框架:https://github.com/getActivity/XXPermissions
+ implementation 'com.github.getActivity:XXPermissions:25.2'
+ // 吐司框架:https://github.com/getActivity/ToastUtils
+ implementation 'com.github.getActivity:Toaster:13.2'
+ // 日志调试框架:https://github.com/getActivity/Logcat ,在debug模式下集成
+ debugImplementation 'com.github.getActivity:Logcat:12.3'
+
+ // PictureSelector图片选择器,需要compileSdkVersion=31 https://github.com/LuckSiege/PictureSelector
+// implementation 'io.github.lucksiege:pictureselector:v3.0.3'
+ //拍照相册选择器、相册编辑添加水印 https://github.com/HuanTanSheng/EasyPhotos(没有适配Android13 相册)
+// implementation 'com.github.HuanTanSheng:EasyPhotos:3.1.5'
+ //压缩图片 https://github.com/zetbaitsu/Compressor
+ implementation 'id.zelory:compressor:3.0.1'
+ //图片裁剪功能https://github.com/CanHub/Android-Image-Cropper
+ implementation 'com.vanniktech:android-image-cropper:4.6.0'
+
+ //******************************************极光推送start*****************************************************
+// https://docs.jiguang.cn/jpush/client/Android/android_guide
+// implementation 'cn.jiguang.sdk:jcore:3.1.2' // 此处以JCore 2.7.2 版本为例。
+// implementation 'cn.jiguang.sdk:jpush:4.6.0' // 此处以JPush 4.0.0 版本为例
+ implementation 'cn.jiguang.sdk:jcore-google:5.1.0' // 此处以JCore 2.7.2 版本为例。
+ implementation 'cn.jiguang.sdk:jpush-google:5.8.0' // 此处以JPush 4.0.0 版本为例
+ // 接入华为厂商
+// implementation 'com.huawei.hms:push:6.1.0.300'
+// implementation 'cn.jiguang.sdk.plugin:huawei:4.0.0'// 极光厂商插件版本与接入 JPush 版本保持一致,下同
+ // 接入 FCM 厂商
+// implementation 'com.google.firebase:firebase-messaging:23.0.0'
+// implementation 'cn.jiguang.sdk.plugin:fcm:4.6.6'
+ // 接入魅族厂商
+// implementation 'cn.jiguang.sdk.plugin:meizu:4.6.0'
+ // 接入 VIVO 厂商
+// implementation 'cn.jiguang.sdk.plugin:vivo:4.6.0'
+ // 接入 OPPO 厂商
+// implementation 'cn.jiguang.sdk.plugin:oppo:4.6.0'
+ // 接入小米厂商
+// implementation 'cn.jiguang.sdk.plugin:xiaomi:4.6.0'
+
+ //******************************************极光推送end*******************************************************
+
+ //其中指代最新Bugly SDK版本号,也可以指定明确的版本号,例如4.0.0
+ implementation 'com.tencent.bugly:crashreport:4.1.9.3'
+ //其中latest.release指代最新Bugly NDK版本号,也可以指定明确的版本号,例如3.9.2
+// implementation 'com.tencent.bugly:nativecrashreport:3.9.2'
+
+ //braintree 信用卡支付https://github.com/braintree/braintree_android
+ implementation 'com.braintreepayments.api:card:4.31.0'
+ //braintree PayPal支付https://developer.paypal.com/braintree/docs/guides/client-sdk/migration/android/v4
+ implementation 'com.braintreepayments.api:paypal:4.31.0'
+ //Stripe 支付https://github.com/stripe/stripe-android
+ implementation 'com.stripe:stripe-android:20.27.0'
+
+ //百度地图基础定位组件
+ implementation 'com.baidu.lbsyun:BaiduMapSDK_Location:9.6.5.1'
+ //地图组件
+ implementation 'com.baidu.lbsyun:BaiduMapSDK_Map:7.5.2'
+ //检索组件
+ implementation 'com.baidu.lbsyun:BaiduMapSDK_Search:7.5.2'
+ //工具组件
+ implementation 'com.baidu.lbsyun:BaiduMapSDK_Util:7.5.2'
+
+ //微信登录、支付
+ implementation 'com.tencent.mm.opensdk:wechat-sdk-android:+'
+ //支付宝支付
+ implementation 'com.alipay.sdk:alipaysdk-android:+@aar'
+
+ //dfu升级https://github.com/NordicSemiconductor/Android-DFU-Library
+ implementation 'no.nordicsemi.android:dfu:2.9.0'
+
+ //适配Android 12以下SplashScreen启动动画,闪屏图片
+ implementation 'androidx.core:core-splashscreen:1.0.1'
+ //优雅、万能自定义日历https://github.com/huanghaibin-dev/CalendarView
+// implementation 'com.haibin:calendarview:3.7.1'
+ //https://github.com/angcyo/CalendarView
+ implementation 'com.github.angcyo:CalendarView:3.7.1.43'
+ //Google出品的流式布局 flexbox-layout 支持RecyclerView https://gitcode.com/google/flexbox-layout?utm_source=csdn_github_accelerator
+ implementation 'com.google.android.flexbox:flexbox:3.0.0'
+ //facebook分享sdk
+// implementation 'com.facebook.android:facebook-android-sdk:latest.release'
+
+}
\ No newline at end of file
diff --git a/app/google-services.json b/app/google-services.json
new file mode 100644
index 0000000..e69de29
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/abbidot/tracker/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/abbidot/tracker/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..2da2670
--- /dev/null
+++ b/app/src/androidTest/java/com/abbidot/tracker/ExampleInstrumentedTest.kt
@@ -0,0 +1,23 @@
+package com.abbidot.tracker
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() { // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.abbidot.tracker", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..487038a
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,610 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/annual_protection_plan_en.html b/app/src/main/assets/annual_protection_plan_en.html
new file mode 100644
index 0000000..41bcca3
--- /dev/null
+++ b/app/src/main/assets/annual_protection_plan_en.html
@@ -0,0 +1,42 @@
+
+
+
+
+
Annual Replacement Protection Plan - Terms & Conditions
+
1. Plan Coverage & Pricing
+
Annual Fee: $12.90 per year
+
Coverage: Provides one free replacement per year for a damaged ABBIDOT Tracker
+
Multi-Year Coverage:
+
Purchasing 1 year entitles you to 1 replacement claim.
+
Purchasing 2 years entitles you to 2 replacement claims (one per year).
+
This pattern continues for longer plans (e.g., 3 years = 3 claims, one per year).
+
+
2. Claim Process
+
To file a claim, submit the following via the ABBIDOT Support Portal:
+
Proof of damage/loss (e.g., photos, police report for lost devices).
+
Original purchase receipt and protection plan confirmation.
+
All claims are subject to verification. Fraudulent claims will result in plan termination without refund.
+
+
3.Cases Not Covered:
+
Intentional Damage - Verified cases of deliberate destruction
+
Unauthorized Modifications - Damage caused by self-disassembly or non-official alterations
+
+
4. Replacement Terms
+
Replacements may include refurbished or new devices (same or equivalent model).
+
Customer covers any applicable shipping fees unless otherwise stated.
+
Manual Refund (After 48 Hours): For subscriptions older than 48 hours but within 1 month, refunds require manual approval. Eligibility: Only applicable to annual (1-year) subscriptions.
+
+
5. Cancellation & Refunds
+
Full refunds available within 48 hours of purchase.
+
By purchasing this plan, you agree to these terms.
+
+
For claims, contact: support@abbidot.com.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/find_device.mp3 b/app/src/main/assets/find_device.mp3
new file mode 100644
index 0000000..dcc4eed
Binary files /dev/null and b/app/src/main/assets/find_device.mp3 differ
diff --git a/app/src/main/assets/fonts/Credit.ttf b/app/src/main/assets/fonts/Credit.ttf
new file mode 100644
index 0000000..00abec8
Binary files /dev/null and b/app/src/main/assets/fonts/Credit.ttf differ
diff --git a/app/src/main/assets/fonts/DinCond_Bold.otf b/app/src/main/assets/fonts/DinCond_Bold.otf
new file mode 100644
index 0000000..9b6cd9d
Binary files /dev/null and b/app/src/main/assets/fonts/DinCond_Bold.otf differ
diff --git a/app/src/main/assets/fonts/Roboto_Bold.ttf b/app/src/main/assets/fonts/Roboto_Bold.ttf
new file mode 100644
index 0000000..91ec212
Binary files /dev/null and b/app/src/main/assets/fonts/Roboto_Bold.ttf differ
diff --git a/app/src/main/assets/fonts/Roboto_Regular.ttf b/app/src/main/assets/fonts/Roboto_Regular.ttf
new file mode 100644
index 0000000..7d9a6c4
Binary files /dev/null and b/app/src/main/assets/fonts/Roboto_Regular.ttf differ
diff --git a/app/src/main/assets/lottie/active_dog.json b/app/src/main/assets/lottie/active_dog.json
new file mode 100644
index 0000000..957744b
--- /dev/null
+++ b/app/src/main/assets/lottie/active_dog.json
@@ -0,0 +1 @@
+{"v":"5.7.8","fr":50,"ip":0,"op":25,"w":900,"h":900,"nm":"dog","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[423.50000000000006,667,0],"ix":2,"l":2},"a":{"a":0,"k":[-42.5,230,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-265,230],[180,230]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.2901960784313726,0.2901960784313726,0.2901960784313726,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":13,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.280000095741,0.280000095741,0.280000095741,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":13.001,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0]},{"t":25,"s":[10]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[90]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":13.001,"s":[90]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100]},{"t":25,"s":[90]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":455,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"ear","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[-14]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":13.001,"s":[-14]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0]},{"t":25,"s":[-14]}],"ix":10},"p":{"a":0,"k":[356.247,24.591,0],"ix":2,"l":2},"a":{"a":0,"k":[86.762,16.905,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[6.047,30.334],[6.448,-4.934],[10.079,-11.171],[-24.71,-24.977],[-15.609,17.99]],"o":[[-2.904,-14.527],[-12.074,9.24],[-19.879,22.036],[20.808,21.034],[23.082,-26.608]],"v":[[40.358,-57.369],[10.962,-59.197],[-22.458,-26.687],[-33.818,50.862],[35.446,37.976]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2901960784313726,0.2901960784313726,0.2901960784313726,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[58.778,72.146],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":455,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"l 4","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[316.531,353.859,0],"ix":2,"l":2},"a":{"a":0,"k":[20.132,95.184,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":3.001,"s":[{"i":[[-0.27,-10.314],[-10.025,-30.105],[-7.439,0.15]],"o":[[-1.35,16.534],[6.761,20.302],[14.884,-0.3]],"v":[[0.132,-75.184],[18.197,26.052],[41.118,67.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":19,"s":[{"i":[[6.845,-41.332],[-31.078,-20.171],[23.303,-11.608]],"o":[[-6.585,39.76],[22.699,14.732],[-45.697,-11.74]],"v":[[0.757,-68.684],[63.973,0.344],[65.868,50.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":31.001,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":35,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":39,"s":[{"i":[[13.707,-39.589],[-21.812,-30.118],[27.944,-1.871]],"o":[[-6.105,17.632],[14.221,19.637],[-45.697,-11.74]],"v":[[0.757,-68.684],[62.79,19.37],[52.868,56.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":45,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":51,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":55,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":58.999,"s":[{"i":[[13.707,-39.589],[-21.812,-30.118],[27.944,-1.871]],"o":[[-6.105,17.632],[14.221,19.637],[-45.697,-11.74]],"v":[[0.757,-68.684],[62.79,19.37],[52.868,56.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":65,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":71,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":75,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":79,"s":[{"i":[[13.707,-39.589],[-21.812,-30.118],[27.944,-1.871]],"o":[[-6.105,17.632],[14.221,19.637],[-45.697,-11.74]],"v":[[0.757,-68.684],[62.79,19.37],[52.868,56.184]],"c":false}]},{"t":85,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.937254961799,0.678431372549,0.011764706817,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":40,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[20.131,95.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":455,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"l 3","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[37.531,349.898,0],"ix":2,"l":2},"a":{"a":0,"k":[20.132,95.184,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":3.001,"s":[{"i":[[-0.27,-10.314],[-10.025,-30.105],[-7.439,0.15]],"o":[[-1.35,16.534],[6.761,20.302],[14.884,-0.3]],"v":[[0.132,-75.184],[18.197,26.052],[41.118,67.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":19,"s":[{"i":[[6.845,-41.332],[-31.078,-20.171],[23.303,-11.608]],"o":[[-6.585,39.76],[22.699,14.732],[-45.697,-11.74]],"v":[[0.757,-68.684],[63.973,0.344],[65.868,50.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":31.001,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":35,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":39,"s":[{"i":[[13.707,-39.589],[-21.812,-30.118],[27.944,-1.871]],"o":[[-6.105,17.632],[14.221,19.637],[-45.697,-11.74]],"v":[[0.757,-68.684],[62.79,19.37],[52.868,56.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":45,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":51,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":55,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":58.999,"s":[{"i":[[13.707,-39.589],[-21.812,-30.118],[27.944,-1.871]],"o":[[-6.105,17.632],[14.221,19.637],[-45.697,-11.74]],"v":[[0.757,-68.684],[62.79,19.37],[52.868,56.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":65,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":71,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":75,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":79,"s":[{"i":[[13.707,-39.589],[-21.812,-30.118],[27.944,-1.871]],"o":[[-6.105,17.632],[14.221,19.637],[-45.697,-11.74]],"v":[[0.757,-68.684],[62.79,19.37],[52.868,56.184]],"c":false}]},{"t":85,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.937254961799,0.678431372549,0.011764706817,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":40,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[20.131,95.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":455,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"body","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[472.81700000000006,392.929,0],"to":[0,2.333,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6,"s":[472.81700000000006,406.929,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":13.001,"s":[472.81700000000006,392.929,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[472.81700000000006,406.929,0],"to":[0,0,0],"ti":[0,2.333,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":25,"s":[472.81700000000006,392.929,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":33.001,"s":[472.81700000000006,392.929,0],"to":[0,2.333,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[472.81700000000006,406.929,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":40,"s":[472.81700000000006,392.929,0],"to":[0,0,0],"ti":[0,-2.333,0]},{"t":46.0009765625,"s":[472.81700000000006,406.929,0]}],"ix":2,"l":2},"a":{"a":0,"k":[267.02,184.77,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[8.555,0],[0,8.325]],"o":[[0,8.325],[-8.548,0],[0,0]],"v":[[15.488,-7.533],[-0.001,7.533],[-15.488,-7.533]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.092349317962,0.075073608698,0.078402522966,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[415.17,77.396],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.421,-3.502],[-4.835,-2.281],[-0.136,0.299],[-1.231,9.972],[-21.503,0],[22.783,-0.837],[4.539,-9.943],[0.084,-0.129],[3.291,1.014],[4.926,7.141]],"o":[[3.1,4.497],[0.051,-0.293],[4.11,-9.001],[-17.676,-5.407],[23.326,0],[-1.53,10.963],[-0.071,0.155],[1.521,2.249],[-8.328,-2.567],[-2.446,-3.542]],"v":[[-22.248,18.173],[-10.232,28.441],[-10.029,27.57],[1.125,-1.66],[6.857,-37.428],[7.656,-0.868],[-4.284,30.93],[-4.554,31.293],[-8.039,36.414],[-27.994,21.533]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2901960784313726,0.2901960784313726,0.2901960784313726,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[503.35,96.036],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-87.495,-9.771],[-16.843,0.916],[10.453,-1.794],[0,0],[5.137,8.279],[-7.464,-12.46]],"o":[[10.186,1.137],[16.851,-0.93],[-1.716,4.068],[-94.107,4.76],[-5.127,-8.314],[7.45,12.475]],"v":[[27.892,52.422],[83.377,52.124],[85.177,12.003],[82.043,25.516],[-74.066,-45.245],[-92.765,-24.181]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2901960784313726,0.2901960784313726,0.2901960784313726,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[336.116,158.467],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[26.417,2.651],[-89.601,18.369],[-22.648,-0.436],[-7.509,1.867],[-1.047,13.715],[-29.532,9.413],[-18.615,-17.337],[0,0],[98.273,-0.709],[25.429,-17.466],[4.244,0.605],[29.493,9.692]],"o":[[-49.64,-13.417],[21.621,-4.888],[7.736,0.149],[24.926,-6.195],[4.432,-57.988],[29.532,-9.416],[47.504,57.771],[0,0],[-19.611,125.548],[-54.196,29.538],[-30.727,-4.405],[-33.152,-10.891]],"v":[[-210.894,149.753],[-168.846,-1.502],[-69.847,-5.473],[-46.879,-8.056],[-4.482,-37.078],[76.472,-171.462],[135.534,-167.183],[257.081,-112.404],[162.26,-22.147],[81.781,154.982],[-39.346,174.857],[-130.154,153.813]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.935686178768,0.677187452129,0.012475915049,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[260.784,184.77],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":455,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"l 2","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[346.531,353.859,0],"ix":2,"l":2},"a":{"a":0,"k":[20.132,95.184,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":-10,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":-6.999,"s":[{"i":[[-0.27,-10.314],[-10.025,-30.105],[-7.439,0.15]],"o":[[-1.35,16.534],[6.761,20.302],[14.884,-0.3]],"v":[[0.132,-75.184],[18.197,26.052],[41.118,67.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-3.999,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":8.999,"s":[{"i":[[6.845,-41.332],[-31.078,-20.171],[23.303,-11.608]],"o":[[-6.585,39.76],[22.699,14.732],[-45.697,-11.74]],"v":[[0.757,-68.684],[63.973,0.344],[65.868,50.184]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":17.999,"s":[{"i":[[-0.27,-10.314],[-10.025,-30.105],[-7.439,0.15]],"o":[[-1.35,16.534],[6.761,20.302],[14.884,-0.3]],"v":[[0.132,-75.184],[18.197,26.052],[41.118,67.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":21,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":34,"s":[{"i":[[6.845,-41.332],[-31.078,-20.171],[23.303,-11.608]],"o":[[-6.585,39.76],[22.699,14.732],[-45.697,-11.74]],"v":[[0.757,-68.684],[63.973,0.344],[65.868,50.184]],"c":false}]},{"t":40,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.8901960784313725,0.5882352941176471,0.08627450980392157,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":40,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[20.131,95.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":436,"st":-20,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"l","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75.531,349.898,0],"ix":2,"l":2},"a":{"a":0,"k":[20.132,95.184,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":-20,"s":[{"i":[[-0.54,-20.628],[-16.404,-26.858],[-18.849,0.38]],"o":[[-2.23,27.314],[16.404,26.858],[29.767,-0.6]],"v":[[0.132,-75.184],[25.441,12.77],[82.368,59.184]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":-10,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":-6.999,"s":[{"i":[[-0.27,-10.314],[-10.025,-30.105],[-7.439,0.15]],"o":[[-1.35,16.534],[6.761,20.302],[14.884,-0.3]],"v":[[0.132,-75.184],[18.197,26.052],[41.118,67.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-3.999,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":8.999,"s":[{"i":[[6.845,-41.332],[-31.078,-20.171],[23.303,-11.608]],"o":[[-6.585,39.76],[22.699,14.732],[-45.697,-11.74]],"v":[[0.757,-68.684],[63.973,0.344],[65.868,50.184]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":17.999,"s":[{"i":[[-0.27,-10.314],[-10.025,-30.105],[-7.439,0.15]],"o":[[-1.35,16.534],[6.761,20.302],[14.884,-0.3]],"v":[[0.132,-75.184],[18.197,26.052],[41.118,67.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":21,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[0.132,-75.184],[-0.041,23.407],[-0.132,75.184]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[0,0],[9.466,-36.43],[16.992,2.263]],"o":[[0,0],[-6.172,23.752],[-43.154,-5.748]],"v":[[0.882,-73.309],[-8.478,10.886],[-41.882,51.309]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":34,"s":[{"i":[[6.845,-41.332],[-31.078,-20.171],[23.303,-11.608]],"o":[[-6.585,39.76],[22.699,14.732],[-45.697,-11.74]],"v":[[0.757,-68.684],[63.973,0.344],[65.868,50.184]],"c":false}]},{"t":40,"s":[{"i":[[-0.54,-20.628],[-22.114,-28.266],[-14.878,0.3]],"o":[[-2.7,33.068],[14.418,18.429],[29.767,-0.6]],"v":[[0.132,-75.184],[36.435,28.698],[82.368,59.184]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.8901960784313725,0.5882352941176471,0.08627450980392157,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":40,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[20.131,95.184],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":436,"st":-20,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"tail","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-17]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":6,"s":[10]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":13.001,"s":[-17]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[10]},{"t":25,"s":[-17]}],"ix":10},"p":{"a":0,"k":[40.937,218.761,0],"ix":2,"l":2},"a":{"a":0,"k":[65.863,31.09,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-9.156,7.505],[-16.639,-7.872],[5.377,-6.122],[4.79,-0.871],[1.446,-0.978],[0.731,-0.835],[8.103,1.145],[7.288,6.21]],"o":[[15.08,-12.354],[8.114,3.844],[-2.411,2.742],[-0.845,1.215],[-0.413,1],[-4.334,4.932],[-11.063,-1.553],[-8.806,-7.506]],"v":[[-32.706,-11.486],[29.921,-11.431],[36.486,5.261],[24.912,10.96],[21.523,14.3],[19.85,17.091],[-0.816,22.695],[-32.553,12.168]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.8901960784313725,0.5882352941176471,0.08627450980392157,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[42.112,24.09],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":455,"st":0,"bm":0}],"markers":[{"tm":0,"cm":"1","dr":0}]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/cat_and_ball.json b/app/src/main/assets/lottie/cat_and_ball.json
new file mode 100644
index 0000000..29ccd9e
--- /dev/null
+++ b/app/src/main/assets/lottie/cat_and_ball.json
@@ -0,0 +1 @@
+{"nm":"Lurking_Сat","ddd":0,"h":512,"w":512,"meta":{"g":"@lottiefiles/toolkit-js 0.33.2"},"layers":[{"ty":4,"nm":"Balls","sr":1,"st":0,"op":300,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":true,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[256,256,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"masksProperties":[{"nm":"Mask 1","inv":false,"mode":"a","x":{"a":0,"k":0,"ix":4},"o":{"a":0,"k":100,"ix":3},"pt":{"a":0,"k":{"c":true,"i":[[141.385,0],[0,-39],[-12.348,-0.061],[-4.405,3.601],[-16.41,0],[-23.383,-0.074],[-8.519,-0.13],[0,5.211]],"o":[[-141.385,0],[0,4.625],[10.781,0.053],[25.845,0.226],[15.087,0],[5.492,3.426],[9.606,0.146],[0,-38]],"v":[[72,147],[-68,198],[-40.652,204.936],[-15.47,200.149],[70,200.375],[148.383,200.324],[173.144,205.104],[201,198]]},"ix":1}}],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ball_1","ix":1,"cix":2,"np":3,"it":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 2","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[14,14],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.7843,0.7843,0.7843],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[2,172],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 3","ix":2,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[33,33],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.651,0.651,0.651],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[1,176.5],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":3,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[40,40],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.5216,0.5216,0.5216],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,180],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"tr","a":{"a":0,"k":[0,180],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-39.25,226.5],"t":0,"ti":[-0.583,4.708],"to":[0.208,-2.083]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-38,214],"t":1,"ti":[-1.25,4.667],"to":[0.583,-4.708]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-35.75,198.25],"t":2,"ti":[-2.042,2.875],"to":[1.25,-4.667]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-30.5,186],"t":3,"ti":[-3.083,1],"to":[2.042,-2.875]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":1},"s":[-23.5,181],"t":4,"ti":[-28.25,0.167],"to":[3.083,-1]},{"o":{"x":0.333,"y":0},"i":{"x":0.833,"y":0.833},"s":[-12,180],"t":5,"ti":[-27.833,0],"to":[28.25,-0.167]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[146,180],"t":34,"ti":[-2.291,0],"to":[4.721,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[158,183],"t":35,"ti":[0,0],"to":[11.216,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[167.5,193],"t":36,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[169.75,204.625],"t":37,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[170.875,216],"t":38,"ti":[0,0],"to":[0,0]},{"s":[172,227.75],"t":39}],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ball_2","ix":2,"cix":2,"np":3,"it":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 2","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[14,14],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.7843,0.7843,0.7843],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[2,172],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 3","ix":2,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[33,33],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.651,0.651,0.651],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[1,176.5],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":3,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[40,40],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.5216,0.5216,0.5216],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,180],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"tr","a":{"a":0,"k":[0,180],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":1,"k":[{"o":{"x":0.419,"y":0.448},"i":{"x":0.833,"y":0.833},"s":[111.745,179.975],"t":0,"ti":[-7.256,0],"to":[14.708,0.014]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[146,180],"t":5,"ti":[-2.291,0],"to":[4.721,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[158,183],"t":6,"ti":[0,0],"to":[11.216,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[167.5,193],"t":7,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[169.75,204.625],"t":8,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[170.875,216],"t":9,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[172,227.75],"t":10,"ti":[35,2.292],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-39.25,226.5],"t":11,"ti":[-0.583,4.708],"to":[-35,-2.292]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-38,214],"t":12,"ti":[-1.25,4.667],"to":[0.583,-4.708]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-35.75,198.25],"t":13,"ti":[-2.042,2.875],"to":[1.25,-4.667]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-30.5,186],"t":14,"ti":[-3.083,1],"to":[2.042,-2.875]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":1},"s":[-23.5,181],"t":15,"ti":[-28.25,0.167],"to":[3.083,-1]},{"o":{"x":0.305,"y":0},"i":{"x":0.726,"y":0.611},"s":[-12,180],"t":16,"ti":[-41.71,-0.039],"to":[20.885,-0.123]},{"o":{"x":0.419,"y":0.448},"i":{"x":0.833,"y":0.833},"s":[111.745,179.975],"t":40,"ti":[-7.256,0],"to":[14.708,0.014]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[146,180],"t":45,"ti":[-2.291,0],"to":[4.721,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[158,183],"t":46,"ti":[0,0],"to":[11.216,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[167.5,193],"t":47,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[169.75,204.625],"t":48,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[170.875,216],"t":49,"ti":[0,0],"to":[0,0]},{"s":[172,227.75],"t":50}],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ball_3","ix":3,"cix":2,"np":3,"it":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 2","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[14,14],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.7843,0.7843,0.7843],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[2,172],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 3","ix":2,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[33,33],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.651,0.651,0.651],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[1,176.5],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":3,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[40,40],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.5216,0.5216,0.5216],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,180],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"tr","a":{"a":0,"k":[0,180],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":1,"k":[{"o":{"x":0.42,"y":0.368},"i":{"x":0.833,"y":0.833},"s":[36.081,179.926],"t":0,"ti":[-18.442,0],"to":[40.511,0.001]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[146,180],"t":16,"ti":[-2.291,0],"to":[4.721,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[158,183],"t":17,"ti":[0,0],"to":[11.216,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[167.5,193],"t":18,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[169.75,204.625],"t":19,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[170.875,216],"t":20,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[172,227.75],"t":21,"ti":[35,2.292],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-39.25,226.5],"t":22,"ti":[-0.583,4.708],"to":[-35,-2.292]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-38,214],"t":23,"ti":[-1.25,4.667],"to":[0.583,-4.708]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-35.75,198.25],"t":24,"ti":[-2.042,2.875],"to":[1.25,-4.667]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[-30.5,186],"t":25,"ti":[-3.083,1],"to":[2.042,-2.875]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":1},"s":[-23.5,181],"t":26,"ti":[-28.25,0.167],"to":[3.083,-1]},{"o":{"x":0.298,"y":0},"i":{"x":0.655,"y":0.439},"s":[-12,180],"t":27,"ti":[-20.63,0],"to":[9.532,-0.056]},{"o":{"x":0.42,"y":0.368},"i":{"x":0.833,"y":0.833},"s":[36.081,179.926],"t":40,"ti":[-18.442,0],"to":[40.511,0.001]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[146,180],"t":56,"ti":[-2.291,0],"to":[4.721,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[158,183],"t":57,"ti":[0,0],"to":[11.216,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[167.5,193],"t":58,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[169.75,204.625],"t":59,"ti":[0,0],"to":[0,0]},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[170.875,216],"t":60,"ti":[0,0],"to":[0,0]},{"s":[172,227.75],"t":61}],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":1},{"ty":4,"nm":"Burrow","sr":1,"st":0,"op":300,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[256,256,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 2","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[54,14],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.4157,0.4157,0.4157],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[174,198],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":2,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[54,14],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.4157,0.4157,0.4157],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-41,198],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":2},{"ty":4,"nm":"Cat_M","sr":1,"st":0,"op":300,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[253.625,248.625,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Group 1","ix":1,"cix":2,"np":4,"it":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Shape 3","ix":1,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":false,"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.25,145.922],[116.375,157.625]]},"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"c":{"a":0,"k":[0.4235,0.4235,0.4235],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-23.75,-1],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Shape 2","ix":2,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":false,"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.375,144],[118.25,158.25]]},"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"c":{"a":0,"k":[0.4235,0.4235,0.4235],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-9.75,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Shape 1","ix":3,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":false,"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.75,145.625],[120.375,157.375]]},"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"c":{"a":0,"k":[0.4235,0.4235,0.4235],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[3,-0.375],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Paw_L","ix":4,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[-18,0],[0,-8.284],[13.807,0],[0,8.284]],"o":[[17.5,0],[0,8.284],[-13.807,0],[0,-8.284]],"v":[[-13,130.125],[12,150],[-13,158.875],[-38,150]]},"ix":2}},{"ty":"gf","bm":0,"hd":false,"mn":"ADBE Vector Graphic - G-Fill","nm":"Gradient Fill 1","e":{"a":0,"k":[-12,150],"ix":6},"g":{"p":3,"k":{"a":0,"k":[0,0.9019607843137255,0.9019607843137255,0.9019607843137255,0.5,0.615686274509804,0.615686274509804,0.615686274509804,1,0.5372549019607843,0.5372549019607843,0.5372549019607843],"ix":9}},"t":2,"a":{"a":0,"k":0,"ix":8},"h":{"a":0,"k":0,"ix":7},"s":{"a":0,"k":[-12,120.5],"ix":5},"r":1,"o":{"a":0,"k":100,"ix":10}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[122,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"tr","a":{"a":0,"k":[109,144.5],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[109,144.5],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Group 2","ix":2,"cix":2,"np":4,"it":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Shape 3","ix":1,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":false,"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.25,145.922],[116.375,157.625]]},"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"c":{"a":0,"k":[0.4235,0.4235,0.4235],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-145.25,-1],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Shape 2","ix":2,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":false,"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.375,144],[118.25,158.25]]},"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"c":{"a":0,"k":[0.4235,0.4235,0.4235],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-131.25,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Shape 1","ix":3,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":false,"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[118.75,145.625],[120.375,157.375]]},"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"c":{"a":0,"k":[0.4235,0.4235,0.4235],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-118.5,-0.375],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Paw_R","ix":4,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[-18,0],[0,-8.284],[13.807,0],[0,8.284]],"o":[[17.5,0],[0,8.284],[-13.807,0],[0,-8.284]],"v":[[-13,130.125],[12,150],[-13,158.875],[-38,150]]},"ix":2}},{"ty":"gf","bm":0,"hd":false,"mn":"ADBE Vector Graphic - G-Fill","nm":"Gradient Fill 1","e":{"a":0,"k":[-12,150],"ix":6},"g":{"p":3,"k":{"a":0,"k":[0,0.9019607843137255,0.9019607843137255,0.9019607843137255,0.5,0.615686274509804,0.615686274509804,0.615686274509804,1,0.5372549019607843,0.5372549019607843,0.5372549019607843],"ix":9}},"t":2,"a":{"a":0,"k":0,"ix":8},"h":{"a":0,"k":0,"ix":7},"s":{"a":0,"k":[-12,120.5],"ix":5},"r":1,"o":{"a":0,"k":100,"ix":10}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"tr","a":{"a":0,"k":[-13,144.5],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-13,144.5],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Head","ix":3,"cix":2,"np":8,"it":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Pupil_R","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[16,16],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.1725,0.1725,0.1176],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[119.617,119.617],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[12.674,117.014],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Pupil_L","ix":2,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[16,16],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.1725,0.1725,0.1176],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[119.617,119.617],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[58.424,117.014],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Eye_R","ix":3,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[26,26],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[1,1,1],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[12.038,112.761],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Eye_L","ix":4,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[26,26],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[1,1,1],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[59.038,112.761],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Nous","ix":5,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[3.5,0],[-1.402,-1.816],[-1.275,-0.083],[-1.626,2.328]],"o":[[-3.5,0],[1.854,2.401],[1.138,0.074],[1.252,-1.793]],"v":[[51.25,124.375],[46.335,126.969],[51,131.125],[55.665,126.969]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.5137,0.5137,0.5137],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[51.032,127.445],"ix":1},"s":{"a":0,"k":[146.102,146.102],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[38.782,130.235],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ear_R","ix":6,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[6.019,3.225],[2.204,-6.427],[-8.575,-8.229],[-0.608,4.024]],"o":[[-4.063,-2.177],[-1.76,5.131],[6.787,6.513],[2.085,-13.805]],"v":[[61.573,58.281],[43.159,80.708],[56.204,93.339],[69.825,103.702]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.6471,0.6471,0.6471],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[58.12,89.316],"ix":1},"s":{"a":0,"k":[-100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[8.179,72.393],"ix":2},"r":{"a":0,"k":21.311,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ear_L","ix":7,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[6.019,3.225],[2.016,-6.488],[-8.515,-6.092],[-0.422,4.048]],"o":[[-4.063,-2.177],[-1.471,4.733],[8.391,6.002],[1.47,-14.115]],"v":[[60.805,57.44],[45.306,81.747],[56.107,91.948],[70.96,105.058]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.6471,0.6471,0.6471],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[57.265,86.752],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[50.449,70.288],"ix":2},"r":{"a":0,"k":-19.904,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Head_cont","ix":8,"cix":2,"np":5,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[-31.127,-0.321],[-10.5,-19.5],[41.517,0.511],[0.221,27.321]],"o":[[28.215,0.291],[0.873,20.012],[-33.054,-0.407],[14.5,-21.5]],"v":[[-0.343,-39.62],[49,0],[0,36.5],[-52,0]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.4235,0.4235,0.4235],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[124.608,114.002],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[31,107],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"tr","a":{"a":0,"k":[29.5,112.007],"ix":1},"s":{"a":0,"k":[120,120],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[42,112.007],"t":0,"ti":[0,0],"to":[-0.833,0]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[37,112.007],"t":20,"ti":[-0.833,0],"to":[0,0]},{"s":[42,112.007],"t":40}],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Paw_2L","ix":4,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[{"c":false,"i":[[-2.621,13.477],[0,0],[0,0]],"o":[[1.75,-9],[0,0],[0,0]],"v":[[-20.875,143.125],[-23.375,120.875],[-71.875,60.875]]}],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[{"c":false,"i":[[-2.621,13.477],[0,0],[0,0]],"o":[[1.75,-9],[0,0],[0,0]],"v":[[-20.875,143.125],[-21.125,119.875],[-37.625,61.375]]}],"t":20},{"s":[{"c":false,"i":[[-2.621,13.477],[0,0],[0,0]],"o":[[1.75,-9],[0,0],[0,0]],"v":[[-20.875,143.125],[-23.375,120.875],[-71.875,60.875]]}],"t":40}],"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"c":{"a":0,"k":[0.2902,0.2902,0.2627],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[136,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Paw_2R","ix":5,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[{"c":false,"i":[[13.336,3.263],[0,0],[0,0]],"o":[[-23.5,-5.75],[0,0],[0,0]],"v":[[-22.375,143.375],[-55.875,129.875],[-51.375,79.875]]}],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[{"c":false,"i":[[13.336,3.263],[0,0],[0,0]],"o":[[-23.5,-5.75],[0,0],[0,0]],"v":[[-22.375,143.375],[-54.375,125.375],[-28.375,71.375]]}],"t":20},{"s":[{"c":false,"i":[[13.336,3.263],[0,0],[0,0]],"o":[[-23.5,-5.75],[0,0],[0,0]],"v":[[-22.375,143.375],[-55.875,129.875],[-51.375,79.875]]}],"t":40}],"ix":2}},{"ty":"st","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Stroke","nm":"Stroke 1","lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"c":{"a":0,"k":[0.2902,0.2902,0.2627],"ix":3}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[0,0],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Body","ix":6,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,42],"ix":3},"s":{"a":0,"k":[132,132],"ix":2}},{"ty":"gf","bm":0,"hd":false,"mn":"ADBE Vector Graphic - G-Fill","nm":"Gradient Fill 1","e":{"a":0,"k":[5.82,46.333],"ix":6},"g":{"p":3,"k":{"a":0,"k":[0,0.9019607843137255,0.9019607843137255,0.9019607843137255,0.5,0.7254901960784313,0.7254901960784313,0.7254901960784313,1,0.2901960784313726,0.2901960784313726,0.2627450980392157],"ix":9}},"t":2,"a":{"a":0,"k":0,"ix":8},"h":{"a":0,"k":0,"ix":7},"s":{"a":0,"k":[-5.908,-34.167],"ix":5},"r":1,"o":{"a":0,"k":100,"ix":10}},{"ty":"tr","a":{"a":0,"k":[0,107.75],"ix":1},"s":{"a":0,"k":[120,120],"ix":3},"sk":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-10],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[10],"t":20},{"s":[-10],"t":40}],"ix":4},"p":{"a":0,"k":[19.996,150],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ass 2","ix":7,"cix":2,"np":4,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[30.074,30.511],[-0.096,-45.043],[59.647,0],[0,59.647],[-15.943,6.605],[-6.201,-28.189],[-30.218,20.85],[-21.128,-14.372],[-17.54,27.841],[21.248,27.859],[-1.256,4.178]],"o":[[4.602,1.255],[0.127,59.647],[-59.647,0],[0,-38.576],[-27.264,31.073],[1.062,4.828],[-24.086,46.914],[28.268,19.228],[11.304,-17.942],[33.512,24.136],[5.756,-19.152]],"v":[[50.943,-78.213],[108,0],[0,108],[-108,0],[-52.568,-78.243],[-85.423,19.317],[-43.954,-53.659],[-38.42,47.521],[58.865,34.07],[46.562,-53.753],[88.469,4.429]]},"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.2902,0.2902,0.2627],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,107.75],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[95.8,104.2],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[94,106],"t":3},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[106,94],"t":13},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[94,106],"t":23},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[106,94],"t":33},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[95.8,104.2],"t":40},{"s":[94,106],"t":43}],"ix":3},"sk":{"a":1,"k":[{"o":{"x":0.333,"y":0.63},"i":{"x":0.833,"y":1},"s":[-8.785],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-10],"t":3},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":0.769},"s":[10],"t":23},{"o":{"x":0.333,"y":0.63},"i":{"x":0.667,"y":1},"s":[-8.785],"t":40},{"s":[-10],"t":43}],"ix":4},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0.22},"i":{"x":0.833,"y":1},"s":[-8.781,150],"t":0,"ti":[-3.13,0],"to":[0,0]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-10,150],"t":3,"ti":[0,0],"to":[3.13,0]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":0.769},"s":[10,150],"t":23,"ti":[0,0],"to":[0,0]},{"o":{"x":0.333,"y":0.628},"i":{"x":0.667,"y":1},"s":[-8.781,150],"t":40,"ti":[0,0],"to":[0,0]},{"s":[-10,150],"t":43}],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ass","ix":8,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":0,"k":{"c":true,"i":[[-59.647,0],[0,-59.647],[59.647,0],[0,59.647]],"o":[[59.647,0],[0,59.647],[-59.647,0],[0,-59.647]],"v":[[0,-108],[108,0],[0,108],[-108,0]]},"ix":2}},{"ty":"gf","bm":0,"hd":false,"mn":"ADBE Vector Graphic - G-Fill","nm":"Gradient Fill 1","e":{"a":0,"k":[90,-14],"ix":6},"g":{"p":3,"k":{"a":0,"k":[0,0.9019607843137255,0.9019607843137255,0.9019607843137255,0.5,0.7254901960784313,0.7254901960784313,0.7254901960784313,1,0.2901960784313726,0.2901960784313726,0.2627450980392157],"ix":9}},"t":2,"a":{"a":0,"k":0,"ix":8},"h":{"a":0,"k":0,"ix":7},"s":{"a":0,"k":[4,-82],"ix":5},"r":1,"o":{"a":0,"k":100,"ix":10}},{"ty":"tr","a":{"a":0,"k":[0,107.75],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[95.8,104.2],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[94,106],"t":3},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[106,94],"t":13},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[94,106],"t":23},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[106,94],"t":33},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[95.8,104.2],"t":40},{"s":[94,106],"t":43}],"ix":3},"sk":{"a":1,"k":[{"o":{"x":0.333,"y":0.63},"i":{"x":0.833,"y":1},"s":[-8.785],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-10],"t":3},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":0.769},"s":[10],"t":23},{"o":{"x":0.333,"y":0.63},"i":{"x":0.667,"y":1},"s":[-8.785],"t":40},{"s":[-10],"t":43}],"ix":4},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0.22},"i":{"x":0.833,"y":1},"s":[-8.781,150],"t":0,"ti":[-3.13,0],"to":[0,0]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-10,150],"t":3,"ti":[0,0],"to":[3.13,0]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":0.769},"s":[10,150],"t":23,"ti":[0,0],"to":[0,0]},{"o":{"x":0.333,"y":0.628},"i":{"x":0.667,"y":1},"s":[-8.781,150],"t":40,"ti":[0,0],"to":[0,0]},{"s":[-10,150],"t":43}],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Tail","ix":9,"cix":2,"np":3,"it":[{"ty":"sh","bm":0,"hd":false,"mn":"ADBE Vector Shape - Group","nm":"Path 1","ix":1,"d":1,"ks":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":false,"i":[[2.63,27.876],[12,17.5],[-27.5,-4]],"o":[[-2.5,-26.5],[-16.1,-23.479],[19.792,2.879]],"v":[[-1,-49],[-32.5,-107],[-2.5,-165.5]]}],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":false,"i":[[4.94,27.059],[7,16.75],[-19.25,18.25]],"o":[[-5,-27],[-8.022,-19.219],[-8.75,-8.25]],"v":[[-1,-49],[-17.25,-105.25],[-24.75,-180.25]]}],"t":5},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":false,"i":[[-0.5,28],[8,23],[-6,28.5]],"o":[[-0.5,-25],[-9.143,-26.285],[2.763,-13.125]],"v":[[-1,-49],[-2.5,-108.5],[-42,-168]]}],"t":10},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":false,"i":[[-1.089,27.485],[-6.418,18.866],[27.5,-7.75]],"o":[[1,-27],[8.25,-24.25],[-7.876,-11.679]],"v":[[-1,-49],[12.25,-106.75],[-26,-152.25]]}],"t":15},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":false,"i":[[-2.786,27.861],[-10.35,20.344],[29,-6.5]],"o":[[3,-30],[14.5,-28.5],[-19.516,4.374]],"v":[[-1,-49],[27,-107.5],[-3,-166]]}],"t":20},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":false,"i":[[0.5,29.5],[-10.75,21.75],[26,1.125]],"o":[[0,-27],[10.868,-21.989],[-11.809,-1.27]],"v":[[-1,-49],[14.75,-113.25],[13.5,-178.625]]}],"t":25},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":false,"i":[[1.926,27.272],[-9.765,20.227],[6,26.917]],"o":[[-0.5,-27.5],[14,-29],[-3.965,-6.248]],"v":[[-1,-49],[-4,-106],[32.5,-165.417]]}],"t":30},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":false,"i":[[4.94,27.059],[7.75,22.25],[-26.75,-10.042]],"o":[[-2,-27.5],[-9.269,-26.612],[9.75,3.958]],"v":[[-1,-49],[-19.25,-107.25],[16.25,-152.958]]}],"t":35},{"s":[{"c":false,"i":[[2.63,27.876],[12,17.5],[-27.5,-4]],"o":[[-2.5,-26.5],[-16.1,-23.479],[19.792,2.879]],"v":[[-1,-49],[-32.5,-107],[-2.5,-165.5]]}],"t":40}],"ix":2}},{"ty":"gs","bm":0,"hd":false,"mn":"ADBE Vector Graphic - G-Stroke","nm":"Gradient Stroke 1","e":{"a":0,"k":[100,0],"ix":5},"g":{"p":3,"k":{"a":0,"k":[0,0.37254901960784315,0.37254901960784315,0.37254901960784315,0.5,0.6666666666666666,0.6666666666666666,0.6666666666666666,1,0.7647058823529411,0.7647058823529411,0.7647058823529411],"ix":8}},"t":2,"a":{"a":0,"k":0,"ix":7},"h":{"a":0,"k":0,"ix":6},"s":{"a":0,"k":[0,0],"ix":4},"lc":2,"lj":2,"ml":1,"o":{"a":0,"k":100,"ix":9},"w":{"a":0,"k":40,"ix":10}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0.297},"i":{"x":0.833,"y":1},"s":[-64.519,0],"t":0,"ti":[-17.92,0],"to":[-7.598,0]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[-77,0],"t":4,"ti":[0,0],"to":[17.92,0]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":0.714},"s":[43,0],"t":24,"ti":[30.722,0],"to":[0,0]},{"o":{"x":0.333,"y":0.615},"i":{"x":0.667,"y":1},"s":[-64.519,0],"t":40,"ti":[0.103,0],"to":[-7.598,0]},{"s":[-77,0],"t":44}],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":3},{"ty":4,"nm":"BG","sr":1,"st":0,"op":300,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6},"sk":{"a":0,"k":0},"p":{"a":0,"k":[256,256,0],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":0,"k":100,"ix":11}},"ef":[],"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 2","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[382,110],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.6784,0.6784,0.6784],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.333,"y":0.63},"i":{"x":0.667,"y":1},"s":[64.751,70.383],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[65.104,70.383],"t":3},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":0.769},"s":[59.286,70.383],"t":23},{"o":{"x":0.333,"y":0.63},"i":{"x":0.667,"y":1},"s":[64.751,70.383],"t":40},{"s":[65.104,70.383],"t":43}],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0.21},"i":{"x":0.667,"y":1},"s":[10.607,119.621],"t":0,"ti":[-1.565,-0.313],"to":[-0.25,-0.05]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[10,119.5],"t":3,"ti":[0,0],"to":[1.565,0.313]},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":0.769},"s":[20,121.5],"t":23,"ti":[2.503,0.501],"to":[0,0]},{"o":{"x":0.333,"y":0.63},"i":{"x":0.667,"y":1},"s":[10.607,119.621],"t":40,"ti":[0.151,0.03],"to":[-0.25,-0.05]},{"s":[10,119.5],"t":43}],"ix":2},"r":{"a":0,"k":4.95,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]},{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":2,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,3],"ix":3},"s":{"a":0,"k":[430,123.822],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.8353,0.8353,0.8353],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[8,122],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":4}],"v":"5.7.5","fr":30,"op":40,"ip":0,"assets":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/dfu_loading.json b/app/src/main/assets/lottie/dfu_loading.json
new file mode 100644
index 0000000..8c0132b
--- /dev/null
+++ b/app/src/main/assets/lottie/dfu_loading.json
@@ -0,0 +1 @@
+{"nm":"Main Scene","ddd":0,"h":200,"w":380,"meta":{"g":"@lottiefiles/creator 1.31.1"},"layers":[{"ty":4,"nm":"Shape Layer 3","sr":1,"st":0,"op":360,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-284,92,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[50,50],"t":17},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[75,75],"t":31},{"s":[50,50],"t":47}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[312,100],"t":17},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[312,60],"t":31},{"s":[312,100],"t":47}],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[25],"t":17},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[100],"t":31},{"s":[25],"t":47}],"ix":11}},"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[120,120],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.0078,0.2863,0.298],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-284,92],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":1},{"ty":4,"nm":"Shape Layer 2","sr":1,"st":0,"op":360,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-284,92,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[50,50],"t":9},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[75,75],"t":23},{"s":[50,50],"t":39}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[192,100],"t":9},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[192,60],"t":23},{"s":[192,100],"t":39}],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[25],"t":9},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[100],"t":23},{"s":[25],"t":39}],"ix":11}},"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[120,120],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.0078,0.2863,0.298],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-284,92],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":2},{"ty":4,"nm":"Shape Layer 1","sr":1,"st":0,"op":360,"ip":0,"hd":false,"ddd":0,"bm":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-284,92,0],"ix":1},"s":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[50,50],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[75,75],"t":14},{"s":[50,50],"t":30}],"ix":6},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[72,100],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[72,60],"t":14},{"s":[72,100],"t":30}],"ix":2},"r":{"a":0,"k":0,"ix":10},"sa":{"a":0,"k":0},"o":{"a":1,"k":[{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[25],"t":0},{"o":{"x":0.333,"y":0},"i":{"x":0.667,"y":1},"s":[100],"t":14},{"s":[25],"t":30}],"ix":11}},"shapes":[{"ty":"gr","bm":0,"hd":false,"mn":"ADBE Vector Group","nm":"Ellipse 1","ix":1,"cix":2,"np":3,"it":[{"ty":"el","bm":0,"hd":false,"mn":"ADBE Vector Shape - Ellipse","nm":"Ellipse Path 1","d":1,"p":{"a":0,"k":[0,0],"ix":3},"s":{"a":0,"k":[120,120],"ix":2}},{"ty":"fl","bm":0,"hd":false,"mn":"ADBE Vector Graphic - Fill","nm":"Fill 1","c":{"a":0,"k":[0.0078,0.2863,0.298],"ix":4},"r":1,"o":{"a":0,"k":100,"ix":5}},{"ty":"tr","a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"sk":{"a":0,"k":0,"ix":4},"p":{"a":0,"k":[-284,92],"ix":2},"r":{"a":0,"k":0,"ix":6},"sa":{"a":0,"k":0,"ix":5},"o":{"a":0,"k":100,"ix":7}}]}],"ind":3}],"v":"5.7.0","fr":60,"op":81,"ip":0,"assets":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/fail_anim.json b/app/src/main/assets/lottie/fail_anim.json
new file mode 100644
index 0000000..91e39a2
--- /dev/null
+++ b/app/src/main/assets/lottie/fail_anim.json
@@ -0,0 +1 @@
+{"v":"5.5.7","meta":{"g":"LottieFiles AE 0.1.20","a":"","k":"","d":"","tc":""},"fr":24,"ip":0,"op":36,"w":64,"h":64,"nm":"Failed","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Dash-2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"a":0,"k":[32.5,33,0],"ix":2},"a":{"a":0,"k":[-3.156,5.437,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[13,5.5],[-29.191,5.379]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0.698039215686,0.141176470588,0.235294117647,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[0.698039215686,0.141176470588,0.235294117647,1]},{"t":24,"s":[1,1,1,1]}],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 35","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[100]},{"t":28,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[100]},{"t":28,"s":[78]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Dash-1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-45,"ix":10},"p":{"a":0,"k":[32.5,33,0],"ix":2},"a":{"a":0,"k":[-3.156,5.437,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[13,5.5],[-29.191,5.379]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0.698039215686,0.141176470588,0.235294117647,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[0.698039215686,0.141176470588,0.235294117647,1]},{"t":24,"s":[1,1,1,1]}],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 35","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100]},{"t":28,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[100]},{"t":28,"s":[78]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Outline","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[32,32,0],"ix":2},"a":{"a":0,"k":[16.383,-9.633,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[56,56],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.9568627450980393,0.2627450980392157,0.21176470588235294,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[16.383,-9.633],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":8,"s":[49]},{"t":16,"s":[87]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":8,"s":[0]},{"t":24,"s":[87]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":720,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Solid","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[0]},{"t":24,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[32,32,0],"ix":2},"a":{"a":0,"k":[16.383,-9.633,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":16,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":24,"s":[110,110,100]},{"t":28,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[56,56],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[16.383,-9.633],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9568627450980393,0.2627450980392157,0.21176470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":720,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/loading_dog.json b/app/src/main/assets/lottie/loading_dog.json
new file mode 100644
index 0000000..2c1be45
--- /dev/null
+++ b/app/src/main/assets/lottie/loading_dog.json
@@ -0,0 +1 @@
+{"v":"5.7.5","fr":30,"ip":0,"op":21,"w":512,"h":512,"nm":"Dog","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Ear","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-37,"ix":10},"p":{"a":0,"k":[51.418,-85.546,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":-2,"s":[{"i":[[0,0],[0,0]],"o":[[-16,-15],[0,0]],"v":[[-78,59.5],[-67.5,-5.5]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":-1,"s":[{"i":[[0,0],[0,0]],"o":[[-8.5,-38.434],[0,0]],"v":[[-78,59.5],[-114.75,38.95]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[-28.5,-34.5],[0,0]],"v":[[-78,59.5],[-124,67.4]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[{"i":[[0,0],[0,0]],"o":[[-25.375,-29.625],[0,0]],"v":[[-78,59.5],[-124.211,46.487]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[0,0],[0,0]],"o":[[-33,-17.5],[0,0]],"v":[[-78,59.5],[-108.75,20.95]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[{"i":[[0,0],[0,0]],"o":[[-20.688,-22.312],[0,0]],"v":[[-78,59.5],[-100.938,8.088]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":8,"s":[{"i":[[0,0],[0,0]],"o":[[-16,-15],[0,0]],"v":[[-78,59.5],[-67.5,-5.5]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":15,"s":[{"i":[[0,0],[0,0]],"o":[[-16,-15],[0,0]],"v":[[-78,59.5],[-41.619,12.027]],"c":false}]},{"t":20,"s":[{"i":[[0,0],[0,0]],"o":[[-16,-15],[0,0]],"v":[[-78,59.5],[-125.832,17.436]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[5,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":57,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Tail","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[-16,-15],[0,0]],"v":[[-78,59.5],[-67.5,-5.5]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[-8.5,-38.434],[0,0]],"v":[[-78,59.5],[-114.75,38.95]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":2,"s":[{"i":[[0,0],[0,0]],"o":[[-28.5,-34.5],[0,0]],"v":[[-78,59.5],[-124,67.4]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[0,0],[0,0]],"o":[[-25.375,-29.625],[0,0]],"v":[[-78,59.5],[-124.375,46.675]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":6,"s":[{"i":[[0,0],[0,0]],"o":[[-33,-17.5],[0,0]],"v":[[-78,59.5],[-108.75,20.95]],"c":false}]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":7,"s":[{"i":[[0,0],[0,0]],"o":[[-20.688,-22.312],[0,0]],"v":[[-78,59.5],[-100.938,8.088]],"c":false}]},{"t":13,"s":[{"i":[[0,0],[0,0]],"o":[[-16,-15],[0,0]],"v":[[-78,59.5],[-67.5,-5.5]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Hose 2","parent":9,"sr":1,"ks":{"o":{"k":[{"s":[100],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[100],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"r":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"p":{"k":[{"s":[-256,-256,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-241.934,0],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-180.066,0],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-166,0],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-166,0],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-168.52,0],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-175.361,0],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-185.444,0],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-197.69,0],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-224.319,0],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-236.558,0],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-246.64,0],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-253.48,0],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-256,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"a":{"k":[{"s":[0,0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"s":{"k":[{"s":[100,100,100],"t":0,"i":{"x":[1,1,1],"y":[1,1,1]},"o":{"x":[0,0,0],"y":[0,0,0]}},{"s":[100,100,100],"t":20,"i":{"x":[1,1,1],"y":[1,1,1]},"o":{"x":[0,0,0],"y":[0,0,0]}}],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"k":[{"s":[4],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[4],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"p":{"k":[{"s":[0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"r":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"ir":{"k":[{"s":[30],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[30],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"is":{"k":[{"s":[100],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[100],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"or":{"k":[{"s":[34.22],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[28.775],"t":1,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[21.608],"t":2,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[27.715],"t":3,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.018],"t":4,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.273],"t":5,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.961],"t":6,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[33.961],"t":7,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.964],"t":8,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.273],"t":9,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.018],"t":10,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[30.334],"t":11,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[25.832],"t":12,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[19.522],"t":13,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[13.08],"t":14,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[10.694],"t":15,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[15.419],"t":16,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[22.624],"t":17,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[29.277],"t":18,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.032],"t":19,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.22],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"os":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"ix":1,"nm":"LineForCurve","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"tm","s":{"k":[{"s":[0.01],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0.01],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"e":{"k":[{"s":[24.99],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[24.99],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"o":{"k":[{"s":[-90],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-90],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"m":1,"ix":2,"nm":"Line Halfer","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"k":[{"s":[0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"a":{"k":[{"s":[-34.22,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-28.775,0],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-21.608,0],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-27.715,0],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.018,0],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.273,0],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.961,0],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-33.961,0],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.964,0],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.273,0],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.018,0],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-30.334,0],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-25.832,0],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-19.522,0],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-13.08,0],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-10.694,0],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-15.419,0],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-22.624,0],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-29.277,0],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.032,0],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.22,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"s":{"k":[{"s":[-100,100],"t":0,"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"s":[-100,100],"t":20,"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}}]},"r":{"k":[{"s":[6.691],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[22.284],"t":1,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[72.181],"t":2,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[123.769],"t":3,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-218.627],"t":4,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-217.52],"t":5,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-214.839],"t":6,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-211.517],"t":7,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-214.829],"t":8,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-217.521],"t":9,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-218.627],"t":10,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-219.684],"t":11,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-223.289],"t":12,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[128.326],"t":13,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[107.576],"t":14,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[62.346],"t":15,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[25.449],"t":16,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[10.793],"t":17,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[5.184],"t":18,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[4.198],"t":19,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[6.691],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"o":{"k":[{"s":[100],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[100],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"sk":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"sa":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"nm":"Transform"}],"nm":"Arc","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[19],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[19],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"k":[{"s":[227,376.474],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[212.714,361.971],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[183.041,320.691],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[158.555,270.2],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[152,243.474],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[151.747,242.558],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[151.117,240.277],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[150.296,237.302],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[151.115,240.268],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[151.748,242.559],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[152,243.474],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[154.286,247.046],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[160.484,256.77],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[169.579,271.153],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[180.581,288.71],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[192.491,307.944],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[204.297,327.367],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[214.987,345.518],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[223.512,360.942],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[228.45,372.412],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[227,376.474],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"BaseHose","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Style","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Hose 2::Ankle","np":0,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[135,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"A","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[200,200],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Hose 2::Hip","np":0,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"B","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"2.07","np":0,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"cl":"07"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Version","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"k":[{"s":[4],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[4],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"p":{"k":[{"s":[0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"r":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"ir":{"k":[{"s":[30],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[30],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"is":{"k":[{"s":[100],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[100],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"or":{"k":[{"s":[34.22],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[28.775],"t":1,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[21.608],"t":2,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[27.715],"t":3,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.018],"t":4,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.273],"t":5,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.961],"t":6,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[33.961],"t":7,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.964],"t":8,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.273],"t":9,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[32.018],"t":10,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[30.334],"t":11,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[25.832],"t":12,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[19.522],"t":13,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[13.08],"t":14,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[10.694],"t":15,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[15.419],"t":16,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[22.624],"t":17,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[29.277],"t":18,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.032],"t":19,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.22],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"os":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"ix":1,"nm":"LineForCurve","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"tm","s":{"k":[{"s":[0.01],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0.01],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"e":{"k":[{"s":[24.99],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[24.99],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"o":{"k":[{"s":[-90],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-90],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"m":1,"ix":2,"nm":"Line Halfer","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"k":[{"s":[0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"a":{"k":[{"s":[-34.22,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-28.775,0],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-21.608,0],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-27.715,0],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.018,0],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.273,0],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.961,0],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-33.961,0],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.964,0],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.273,0],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-32.018,0],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-30.334,0],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-25.832,0],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-19.522,0],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-13.08,0],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-10.694,0],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-15.419,0],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-22.624,0],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-29.277,0],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.032,0],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.22,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"s":{"k":[{"s":[-100,100],"t":0,"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"s":[-100,100],"t":20,"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}}]},"r":{"k":[{"s":[6.691],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[22.284],"t":1,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[72.181],"t":2,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[123.769],"t":3,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-218.627],"t":4,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-217.52],"t":5,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-214.839],"t":6,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-211.517],"t":7,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-214.829],"t":8,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-217.521],"t":9,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-218.627],"t":10,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-219.684],"t":11,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-223.289],"t":12,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[128.326],"t":13,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[107.576],"t":14,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[62.346],"t":15,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[25.449],"t":16,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[10.793],"t":17,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[5.184],"t":18,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[4.198],"t":19,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[6.691],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"ArcMath","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"k":[{"s":[227,376.474],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[212.714,361.971],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[183.041,320.691],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[158.555,270.2],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[152,243.474],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[151.747,242.558],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[151.117,240.277],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[150.296,237.302],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[151.115,240.268],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[151.748,242.559],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[152,243.474],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[154.286,247.046],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[160.484,256.77],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[169.579,271.153],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[180.581,288.71],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[192.491,307.944],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[204.297,327.367],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[214.987,345.518],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[223.512,360.942],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[228.45,372.412],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[227,376.474],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Admin","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Hose 1","parent":9,"sr":1,"ks":{"o":{"k":[{"s":[100],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[100],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"r":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"p":{"k":[{"s":[-256,-256,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-241.934,0],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-180.066,0],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-166,0],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-166,0],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-168.52,0],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-175.361,0],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-185.444,0],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-197.69,0],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-224.319,0],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-236.558,0],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-246.64,0],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-253.48,0],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-256,-256,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"a":{"k":[{"s":[0,0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"s":{"k":[{"s":[100,100,100],"t":0,"i":{"x":[1,1,1],"y":[1,1,1]},"o":{"x":[0,0,0],"y":[0,0,0]}},{"s":[100,100,100],"t":20,"i":{"x":[1,1,1],"y":[1,1,1]},"o":{"x":[0,0,0],"y":[0,0,0]}}],"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"k":[{"s":[4],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[4],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"p":{"k":[{"s":[0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"r":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"ir":{"k":[{"s":[30],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[30],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"is":{"k":[{"s":[100],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[100],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"or":{"k":[{"s":[34.237],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[28.107],"t":1,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[24.524],"t":2,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[33.886],"t":3,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.418],"t":4,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.45],"t":5,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.592],"t":6,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.903],"t":7,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.593],"t":8,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.45],"t":9,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.418],"t":10,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.694],"t":11,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[30.098],"t":12,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[23.681],"t":13,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[17.055],"t":14,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[13.542],"t":15,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[16.458],"t":16,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[29.364],"t":18,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.146],"t":19,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.237],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"os":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"ix":1,"nm":"LineForCurve","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"tm","s":{"k":[{"s":[0.01],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0.01],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"e":{"k":[{"s":[24.99],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[24.99],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"o":{"k":[{"s":[-90],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-90],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"m":1,"ix":2,"nm":"Line Halfer","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"k":[{"s":[0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"a":{"k":[{"s":[-34.237,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-28.107,0],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-24.524,0],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-33.886,0],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.418,0],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.45,0],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.592,0],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.903,0],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.593,0],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.45,0],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.418,0],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.694,0],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-30.098,0],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-23.681,0],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-17.055,0],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-13.542,0],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-16.458,0],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-29.364,0],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.146,0],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.237,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"s":{"k":[{"s":[-100,100],"t":0,"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"s":[-100,100],"t":20,"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}}]},"r":{"k":[{"s":[84.81],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[68.487],"t":1,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[15.783],"t":2,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-27.715],"t":3,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-44.444],"t":4,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-45.558],"t":5,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-48.322],"t":6,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-51.882],"t":7,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-48.332],"t":8,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-45.556],"t":9,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-44.444],"t":10,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-43.336],"t":11,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-39.67],"t":12,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-31.682],"t":13,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-14.22],"t":14,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[20.836],"t":15,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[57.365],"t":16,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[75.994],"t":17,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[84.074],"t":18,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[86.868],"t":19,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[84.81],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"o":{"k":[{"s":[100],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[100],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"sk":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"sa":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"nm":"Transform"}],"nm":"Arc","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"k":[{"s":[19],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[19],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"k":[{"s":[257,375.694],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[272.158,360.89],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[304.929,323.777],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[333.758,276.805],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.5,249],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.546,247.998],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.662,245.501],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.812,242.247],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.662,245.492],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.546,247.999],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.5,249],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[337.044,252.445],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[330.381,261.815],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[320.59,275.659],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[308.722,292.533],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[295.839,310.98],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[283.016,329.554],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[271.317,346.829],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[261.825,361.378],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[255.77,371.941],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[257,375.694],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"BaseHose","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Style","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Hose 1::Ankle","np":0,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[135,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"A","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[200,200],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Hose 1::Hip","np":0,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"B","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"2.07","np":0,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false,"cl":"07"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Version","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"sr","sy":1,"d":1,"pt":{"k":[{"s":[4],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[4],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"p":{"k":[{"s":[0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"r":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"ir":{"k":[{"s":[30],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[30],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"is":{"k":[{"s":[100],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[100],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"or":{"k":[{"s":[34.237],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[28.107],"t":1,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[24.524],"t":2,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[33.886],"t":3,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.418],"t":4,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.45],"t":5,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.592],"t":6,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.903],"t":7,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.593],"t":8,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.45],"t":9,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[36.418],"t":10,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.694],"t":11,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[30.098],"t":12,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[23.681],"t":13,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[17.055],"t":14,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[13.542],"t":15,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[16.458],"t":16,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[29.364],"t":18,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.146],"t":19,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[34.237],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"os":{"k":[{"s":[0],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"ix":1,"nm":"LineForCurve","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"tm","s":{"k":[{"s":[0.01],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[0.01],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"e":{"k":[{"s":[24.99],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[24.99],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"o":{"k":[{"s":[-90],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-90],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"m":1,"ix":2,"nm":"Line Halfer","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"k":[{"s":[0,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[0,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"a":{"k":[{"s":[-34.237,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-28.107,0],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-24.524,0],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-33.886,0],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.418,0],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.45,0],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.592,0],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.903,0],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.593,0],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.45,0],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-36.418,0],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.694,0],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-30.098,0],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-23.681,0],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-17.055,0],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-13.542,0],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-16.458,0],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-29.364,0],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.146,0],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-34.237,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"s":{"k":[{"s":[-100,100],"t":0,"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"s":[-100,100],"t":20,"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}}]},"r":{"k":[{"s":[84.81],"t":0,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[68.487],"t":1,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[15.783],"t":2,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-27.715],"t":3,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-44.444],"t":4,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-45.558],"t":5,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-48.322],"t":6,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-51.882],"t":7,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-48.332],"t":8,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-45.556],"t":9,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-44.444],"t":10,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-43.336],"t":11,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-39.67],"t":12,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-31.682],"t":13,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[-14.22],"t":14,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[20.836],"t":15,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[57.365],"t":16,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[75.994],"t":17,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[84.074],"t":18,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[86.868],"t":19,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}},{"s":[84.81],"t":20,"i":{"x":[1],"y":[1]},"o":{"x":[0],"y":[0]}}]},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"ArcMath","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"k":[{"s":[257,375.694],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[272.158,360.89],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[304.929,323.777],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[333.758,276.805],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.5,249],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.546,247.998],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.662,245.501],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.812,242.247],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.662,245.492],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.546,247.999],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[339.5,249],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[337.044,252.445],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[330.381,261.815],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[320.59,275.659],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[308.722,292.533],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[295.839,310.98],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[283.016,329.554],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[271.317,346.829],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[261.825,361.378],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[255.77,371.941],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[257,375.694],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}]},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Admin","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Body","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[256,256,0],"to":[0,-15,0],"ti":[0,15,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":4,"s":[256,166,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[256,166,0],"to":[0,15,0],"ti":[0,-15,0]},{"t":20,"s":[256,256,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[130.039,52.867],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":74,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-13.98,65.434],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Body","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Neck","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[-25]},{"t":20,"s":[0]}],"ix":10},"p":{"a":0,"k":[30.5,48,0],"ix":2,"l":2},"a":{"a":0,"k":[30.5,48,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[21.223,63.195],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":74,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[30.611,29.598],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Neck","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Head","parent":10,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[18]},{"t":20,"s":[0]}],"ix":10},"p":{"a":0,"k":[30,5.5,0],"ix":2,"l":2},"a":{"a":0,"k":[30,8,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2.313,3.227],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.2196078431372549,0.2901960784313726,0.8274509803921568,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2196078431372549,0.2901960784313726,0.8274509803921568,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[50.539,7.052],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[-7.886,10.149],[0,0]],"o":[[0,0],[0,0],[0,0],[4.335,-5.58],[0,0]],"v":[[29,-0.5],[29,29],[71.5,29],[89.386,18.851],[93.5,-0.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.156,0.299],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Head","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Square Solid","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[45]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[90]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[135]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[180]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[225]},{"t":60,"s":[270]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[256,276,0],"to":[0,-8.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":10,"s":[256,224,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":20,"s":[256,276,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":30,"s":[256,224,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":40,"s":[256,276,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":50,"s":[256,224,0],"to":[0,0,0],"ti":[0,-8.667,0]},{"t":60,"s":[256,276,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[242.574,242.574],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2196078431372549,0.2901960784313726,0.8274509803921568,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":21,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Square","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[45]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[90]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[135]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[180]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[225]},{"t":60,"s":[270]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[256,276,0],"to":[0,-8.667,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":10,"s":[256,224,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":20,"s":[256,276,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":30,"s":[256,224,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":40,"s":[256,276,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":50,"s":[256,224,0],"to":[0,0,0],"ti":[0,-8.667,0]},{"t":60,"s":[256,276,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[255.574,255.574],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":14,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.2196078431372549,0.2901960784313726,0.8274509803921568,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":8,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":21,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/logo_loader.json b/app/src/main/assets/lottie/logo_loader.json
new file mode 100644
index 0000000..8613365
--- /dev/null
+++ b/app/src/main/assets/lottie/logo_loader.json
@@ -0,0 +1 @@
+{"v":"5.5.7","meta":{"g":"LottieFiles AE 0.1.21","a":"","k":"","d":"","tc":""},"fr":30,"ip":0,"op":50,"w":600,"h":600,"nm":"Infinity","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 2c","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[266.899,151.199,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-39.09,0],[0,42.016]],"o":[[22.67,22.309],[42.017,0],[0,-43.441]],"v":[[25.726,26.124],[115.7,76.199],[191.899,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":28,"s":[30]},{"t":33,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":27,"s":[30]},{"t":32,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.6,1,0.941176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":27,"s":[30]},{"t":33,"s":[25]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[266.899,151.199],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 2b","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":18,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":26,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":36,"s":[100]},{"t":38,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[266.899,151.199,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,43.44],[-42.016,0],[-22.67,-22.309],[0,0],[-39.09,0],[0,42.016],[42.329,0]],"o":[[-42.329,0],[0,-42.017],[39.088,0],[0,0],[22.67,22.309],[42.017,0],[0,-43.441],[0,0]],"v":[[-117.649,76.199],[-191.899,0],[-115.699,-76.199],[-25.728,-26.127],[25.726,26.124],[115.7,76.199],[191.899,0],[117.649,-76.199]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":23,"s":[30]},{"t":39,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":18,"s":[30]},{"t":38,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.4,0.944999964097,0.882000014361,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":23,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[30]},{"t":38,"s":[5]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[266.899,151.199],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Path 2a","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":21,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":27,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":36,"s":[100]},{"t":41,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[266.899,151.199,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,43.44],[-42.016,0],[-22.67,-22.309],[0,0],[-39.09,0],[0,42.016],[42.329,0]],"o":[[-42.329,0],[0,-42.017],[39.088,0],[0,0],[22.67,22.309],[42.017,0],[0,-43.441],[0,0]],"v":[[-117.649,76.199],[-191.899,0],[-115.699,-76.199],[-25.728,-26.127],[25.726,26.124],[115.7,76.199],[191.899,0],[117.649,-76.199]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[30]},{"t":41,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":21,"s":[30]},{"t":38,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.047058823529,0.658823529412,0.674509803922,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":23,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":31,"s":[25]},{"t":37,"s":[5]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[266.899,151.199],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Path 1d","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":18,"s":[100]},{"t":24,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[266.899,151.199,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,43.44],[42.016,0],[22.67,-22.309],[0,0],[39.09,0],[0,42.016],[-42.329,0]],"o":[[42.329,0],[0,-42.017],[-39.088,0],[0,0],[-22.67,22.309],[-42.017,0],[0,-43.441],[0,0]],"v":[[117.649,76.199],[191.899,0],[115.699,-76.199],[25.728,-26.127],[-25.726,26.124],[-115.7,76.199],[-191.899,0],[-117.649,-76.199]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[30]},{"t":24,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[30]},{"t":21,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.486274509804,0.329411764706,0.925490196078,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[30]},{"t":20,"s":[5]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[266.899,151.199],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Path 1c","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":19,"s":[100]},{"t":25,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[266.899,151.199,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,43.44],[42.016,0],[22.67,-22.309],[0,0],[39.09,0],[0,42.016],[-42.329,0]],"o":[[42.329,0],[0,-42.017],[-39.088,0],[0,0],[-22.67,22.309],[-42.017,0],[0,-43.441],[0,0]],"v":[[117.649,76.199],[191.899,0],[115.699,-76.199],[25.728,-26.127],[-25.726,26.124],[-115.7,76.199],[-191.899,0],[-117.649,-76.199]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":7,"s":[30]},{"t":25,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":2,"s":[30]},{"t":22,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.388235294118,0.490196078431,0.921568627451,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[30]},{"t":20,"s":[5]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[266.899,151.199],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Path 1b","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100]},{"t":26,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[266.899,151.199,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,43.44],[42.016,0],[22.67,-22.309],[0,0],[39.09,0],[0,42.016],[-42.329,0]],"o":[[42.329,0],[0,-42.017],[-39.088,0],[0,0],[-22.67,22.309],[-42.017,0],[0,-43.441],[0,0]],"v":[[117.649,76.199],[191.899,0],[115.699,-76.199],[25.728,-26.127],[-25.726,26.124],[-115.7,76.199],[-191.899,0],[-117.649,-76.199]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":8,"s":[30]},{"t":26,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":3,"s":[30]},{"t":23,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.682352941176,0.866666666667,0.976470588235,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":2,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[30]},{"t":20,"s":[5]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[266.899,151.199],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Path 1a","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100]},{"t":25,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[266.899,151.199,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,43.44],[42.016,0],[22.67,-22.309],[0,0],[39.09,0],[0,42.016],[-42.329,0]],"o":[[42.329,0],[0,-42.017],[-39.088,0],[0,0],[-22.67,22.309],[-42.017,0],[0,-43.441],[0,0]],"v":[[117.649,76.199],[191.899,0],[115.699,-76.199],[25.728,-26.127],[-25.726,26.124],[-115.7,76.199],[-191.899,0],[-117.649,-76.199]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":18,"s":[30]},{"t":25,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[30]},{"t":21,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0.321568627451,0.176470588235,0.501960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[25]},{"t":20,"s":[5]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[266.899,151.199],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"path","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/map_lowpower.json b/app/src/main/assets/lottie/map_lowpower.json
new file mode 100644
index 0000000..3ac78c5
--- /dev/null
+++ b/app/src/main/assets/lottie/map_lowpower.json
@@ -0,0 +1 @@
+{"v":"5.5.9","fr":60,"ip":0,"op":60,"w":20,"h":35,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":14,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":28,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":42,"s":[100]},{"t":56,"s":[4]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[10,28.636363636363626,0],"ix":2},"a":{"a":0,"k":[6.75,2.25,0],"ix":1},"s":{"a":0,"k":[90.9090909090909,92.10526315789475,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.552,0],[0,0],[0,-0.553],[0,0],[0.553,0],[0,0],[0,0.553],[0,0]],"o":[[0,0],[0.553,0],[0,0],[0,0.553],[0,0],[-0.552,0],[0,0],[0,-0.553]],"v":[[-5.5,-2],[5.5,-2],[6.5,-1],[6.5,1],[5.5,2],[-5.5,2],[-6.5,1],[-6.5,-1]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9137254901960784,0.8509803921568627,0.08235294117647059,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[6.75,2.25],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Layer 2 Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[10,17.72727272727273,0],"ix":2},"a":{"a":0,"k":[12,19.5,0],"ix":1},"s":{"a":0,"k":[90.9090909090909,92.10526315789475,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.104,0],[0,0],[0,-1.104],[0,0],[1.104,0],[0,0],[0,1.104],[0,0]],"o":[[0,0],[1.104,0],[0,0],[0,1.104],[0,0],[-1.104,0],[0,0],[0,-1.104]],"v":[[-8,-15.5],[8,-15.5],[10,-13.5],[10,13.5],[8,15.5],[-8,15.5],[-10,13.5],[-10,-13.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.9137254901960784,0.8509803921568627,0.08235294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[12,21.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[14,1.5],[10,1.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.9137254901960784,0.8509803921568627,0.08235294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/pic_map_lost.json b/app/src/main/assets/lottie/pic_map_lost.json
new file mode 100644
index 0000000..67c4160
--- /dev/null
+++ b/app/src/main/assets/lottie/pic_map_lost.json
@@ -0,0 +1 @@
+{"v":"5.4.4","fr":30,"ip":0,"op":90,"w":100,"h":100,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Adjustment Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2},"a":{"a":0,"k":[250,250,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100],"e":[26,26,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6.333,"s":[26,26,100],"e":[20,20,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":11.833,"s":[20,20,100],"e":[24,24,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":16.418,"s":[24,24,100],"e":[22,22,100]},{"t":19.1675007807083}],"ix":6}},"ao":0,"ip":0,"op":900.000036657751,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"stroke","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":48,"s":[0],"e":[-4]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50.25,"s":[-4],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":52.5,"s":[3],"e":[-2]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":54.75,"s":[-2],"e":[4]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":57,"s":[4],"e":[0]},{"t":60.0000024438501}],"ix":10},"p":{"a":0,"k":[258.75,237,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[110,110,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-7.104,12.304],[0,0],[0,0],[-7.104,-12.304],[0,0],[0,0],[14.207,0]],"o":[[0,0],[-14.207,0],[0,0],[0,0],[7.104,-12.304],[0,0],[0,0],[7.104,12.304],[0,0]],"v":[[0,105.676],[-98.937,105.676],[-114.92,77.992],[-65.452,-7.69],[-15.983,-93.372],[15.983,-93.372],[65.452,-7.69],[114.921,77.992],[98.937,105.676]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":12,"s":[258.75,268.805,0],"e":[258.75,283.75,0],"to":[0,2.491,0],"ti":[0,-2.491,0]},{"t":23.0000009368092}],"ix":2},"a":{"a":0,"k":[16,38,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":16,"s":[91.667,0,100],"e":[91.667,99,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":23.555,"s":[91.667,99,100],"e":[91.667,93.5,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":29.223,"s":[91.667,93.5,100],"e":[91.667,91.63,100]},{"t":33.0000013441176}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,-8.284],[8.284,0],[0,8.284]],"o":[[8.284,0],[0,8.284],[-8.284,0],[0,-8.284]],"v":[[0,-15],[15,0],[0,15],[-15,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[16,53],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 2","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[258.75,271.1,0],"ix":2},"a":{"a":0,"k":[0,76.865,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":18,"s":[50.417,0,100],"e":[50.417,55,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":22,"s":[50.417,55,100],"e":[50.417,47.3,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":26,"s":[50.417,47.3,100],"e":[50.417,50.38,100]},{"t":30.0000012219251}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.327,29.458],[0,0],[2.522,-56],[-6.482,-25.766],[-4.199,16.689]],"o":[[-2.522,-56],[0,0],[-1.327,29.458],[4.199,16.689],[6.482,-25.766]],"v":[[23.327,-25.037],[0,-78.037],[-23.327,-25.037],[-11.647,64.349],[11.647,64.349]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"body","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":27,"s":[0],"e":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":29.728,"s":[5],"e":[-3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":32.455,"s":[-3],"e":[2]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":35.183,"s":[2],"e":[-5]},{"i":{"x":[0.4],"y":[0.4]},"o":{"x":[0.333],"y":[0]},"t":37.91,"s":[-5],"e":[0]},{"t":42.0000017106951}],"ix":10},"p":{"a":0,"k":[249.583,248.917,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[110,110,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-7.104,12.304],[0,0],[0,0],[-7.104,-12.304],[0,0],[0,0],[14.207,0]],"o":[[0,0],[-14.207,0],[0,0],[0,0],[7.104,-12.304],[0,0],[0,0],[7.104,12.304],[0,0]],"v":[[0,105.676],[-98.937,105.676],[-114.92,77.992],[-65.452,-7.69],[-15.983,-93.372],[15.983,-93.372],[65.452,-7.69],[114.921,77.992],[98.937,105.676]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.8274509803921568,1,0.3254901960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/pic_map_nosignal.json b/app/src/main/assets/lottie/pic_map_nosignal.json
new file mode 100644
index 0000000..1eae40c
--- /dev/null
+++ b/app/src/main/assets/lottie/pic_map_nosignal.json
@@ -0,0 +1 @@
+{"v":"5.5.8","fr":30,"ip":0,"op":120,"w":100,"h":100,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Layer 85","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64.47600000000001,75.76300000000002,0],"ix":2},"a":{"a":0,"k":[43.428,77.289,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.32,0.32,0.32],"y":[1.27,1.27,1]},"o":{"x":[0.54,0.54,0.54],"y":[0,0,0]},"t":41,"s":[0,0,100]},{"t":61,"s":[33.33333333333334,33.33333333333334,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-5.031],[5.031,0],[0,5.031],[-5.031,0]],"o":[[0,5.031],[-5.031,0],[0,-5.031],[5.031,0]],"v":[[52.734,51.625],[43.625,60.734],[34.516,51.625],[43.625,42.516]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[43,-2],[43,29]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":16,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.8274509803921568,1,0.3254901960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-37.435,79],[43.428,-52.423],[124.292,79]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":16,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.8274509803921568,1,0.3254901960784314,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":41,"op":201,"st":21,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Isolation Mode 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[37.21300000000001,45.867666666666686,0],"ix":2},"a":{"a":0,"k":[-38.361,-12.397,0],"ix":1},"s":{"a":0,"k":[33.33333333333334,33.33333333333334,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-80.779]],"o":[[80.779,0],[0,0]],"v":[[-111.492,-85.529],[34.771,60.734]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.8274509803921568,1,0.3254901960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":18,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0]},{"t":49,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim In Path","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":29,"op":189,"st":9,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Isolation Mode 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[31.03933333333334,52.04133333333335,0],"ix":2},"a":{"a":0,"k":[-56.882,6.124,0],"ix":1},"s":{"a":0,"k":[33.33333333333334,33.33333333333334,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-60.321]],"o":[[60.321,0],[0,0]],"v":[[-111.492,-48.487],[-2.272,60.734]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.8274509803921568,1,0.3254901960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":18,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[0]},{"t":45,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim In Path","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":25,"op":185,"st":5,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Isolation Mode","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[25.122000000000007,60.75800000000002,0],"ix":2},"a":{"a":0,"k":[-74.634,32.274,0],"ix":1},"s":{"a":0,"k":[33.33333333333334,33.33333333333334,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-40.465],[0,0]],"o":[[40.465,0],[0,0],[0,0]],"v":[[-111.268,-12.451],[-38,60.734],[-38,77]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.8274509803921568,1,0.3254901960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":18,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"t":40,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim In Path","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":20,"op":180,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.575000000000006,66.50566666666668,0],"ix":2},"a":{"a":0,"k":[-100.275,49.517,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.32,0.32,0.32],"y":[1,1,1]},"o":{"x":[0.17,0.17,0.17],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":20,"s":[33.33333333333334,33.33333333333334,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-15.604],[15.604,0],[0,15.604],[-15.604,0]],"o":[[0,15.604],[-15.604,0],[0,-15.604],[15.604,0]],"v":[[-72.021,49.517],[-100.275,77.771],[-128.529,49.517],[-100.275,21.263]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.8274509803921568,1,0.3254901960784314,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":12,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.07058823529411765,0.09803921568627451,0.11372549019607843,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":180,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/searching_tracker.json b/app/src/main/assets/lottie/searching_tracker.json
new file mode 100644
index 0000000..35eafb1
--- /dev/null
+++ b/app/src/main/assets/lottie/searching_tracker.json
@@ -0,0 +1 @@
+{"v":"5.4.4","fr":30,"ip":0,"op":61,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 18","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":60,"s":[50,50],"e":[400,400]},{"t":120}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[100],"e":[0]},{"t":120}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[3],"e":[0]},{"t":120}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":60,"op":121,"st":60,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 17","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":50,"s":[50,50],"e":[400,400]},{"t":110}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":50,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":80,"s":[100],"e":[0]},{"t":110}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":50,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":80,"s":[3],"e":[0]},{"t":110}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":50,"op":111,"st":50,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 16","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":40,"s":[50,50],"e":[400,400]},{"t":100}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":40,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":70,"s":[100],"e":[0]},{"t":100}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":40,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":70,"s":[3],"e":[0]},{"t":100}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":40,"op":101,"st":40,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 15","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":30,"s":[50,50],"e":[400,400]},{"t":90}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":30,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[100],"e":[0]},{"t":90}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":30,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[3],"e":[0]},{"t":90}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":91,"st":30,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Shape Layer 14","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":20,"s":[50,50],"e":[400,400]},{"t":80}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":20,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[100],"e":[0]},{"t":80}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":20,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[3],"e":[0]},{"t":80}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":20,"op":81,"st":20,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Shape Layer 13","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":10,"s":[50,50],"e":[400,400]},{"t":70}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":10,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[100],"e":[0]},{"t":70}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":10,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[3],"e":[0]},{"t":70}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":10,"op":71,"st":10,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Shape Layer 12","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":0,"s":[50,50],"e":[400,400]},{"t":60}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[100],"e":[0]},{"t":60}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[3],"e":[0]},{"t":60}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":61,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Shape Layer 11","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":-10,"s":[50,50],"e":[400,400]},{"t":50}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-10,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100],"e":[0]},{"t":50}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-10,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[3],"e":[0]},{"t":50}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-10,"op":51,"st":-10,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Shape Layer 10","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":-20,"s":[50,50],"e":[400,400]},{"t":40}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-20,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[100],"e":[0]},{"t":40}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-20,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[3],"e":[0]},{"t":40}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-20,"op":41,"st":-20,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Shape Layer 9","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":-30,"s":[50,50],"e":[400,400]},{"t":30}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-30,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100],"e":[0]},{"t":30}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-30,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[3],"e":[0]},{"t":30}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-30,"op":31,"st":-30,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Shape Layer 8","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":-40,"s":[50,50],"e":[400,400]},{"t":20}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-40,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-10,"s":[100],"e":[0]},{"t":20}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-40,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-10,"s":[3],"e":[0]},{"t":20}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-40,"op":21,"st":-40,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":80,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200.063,200,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":-50,"s":[50,50],"e":[400,400]},{"t":10}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529422283,0.823529422283,0.823529422283,1],"ix":3},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-50,"s":[0],"e":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-20,"s":[100],"e":[0]},{"t":10}],"ix":4,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":-50,"s":[0],"e":[3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-20,"s":[3],"e":[0]},{"t":10}],"ix":5,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-50,"op":11,"st":-50,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.426},"o":{"x":0.333,"y":0},"t":0,"s":[200,190,0],"e":[210,200,0],"to":[5.523,0,0],"ti":[0,-5.523,0]},{"i":{"x":0.667,"y":0.653},"o":{"x":0.333,"y":0.305},"t":19.581,"s":[210,200,0],"e":[200,210,0],"to":[0,5.523,0],"ti":[5.523,0,0]},{"i":{"x":0.667,"y":0.695},"o":{"x":0.333,"y":0.347},"t":30,"s":[200,210,0],"e":[190,200,0],"to":[-5.523,0,0],"ti":[0,5.523,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0.574},"t":40.419,"s":[190,200,0],"e":[200,190,0],"to":[0,-5.523,0],"ti":[-5.523,0,0]},{"t":60}],"ix":2,"x":"var $bm_rt;\n$bm_rt = loopOut('cycle', 0);"},"a":{"a":0,"k":[-3.25,-7.5,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[29,29],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529481888,0.823529481888,0.823529481888,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-3.25,-7.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[9.75,10.5],[21.25,22.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.823529481888,0.823529481888,0.823529481888,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-3.25,-7.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/app/src/main/assets/lottie/success_anim.json b/app/src/main/assets/lottie/success_anim.json
new file mode 100644
index 0000000..33fbb5d
--- /dev/null
+++ b/app/src/main/assets/lottie/success_anim.json
@@ -0,0 +1 @@
+{"v": "5.5.7", "meta": {"g": "LottieFiles AE 0.1.21", "a": "", "k": "", "d": "", "tc": ""}, "fr": 29.9700012207031, "ip": 0, "op": 60.0000024438501, "w": 120, "h": 120, "nm": "sucess", "ddd": 0, "assets": [], "layers": [{"ddd": 0, "ind": 1, "ty": 3, "nm": "scale up null", "sr": 1, "ks": {"o": {"a": 0, "k": 0, "ix": 11}, "r": {"a": 0, "k": 0, "ix": 10}, "p": {"a": 0, "k": [60, 60, 0], "ix": 2}, "a": {"a": 0, "k": [0, 0, 0], "ix": 1}, "s": {"a": 1, "k": [{"i": {"x": [0.833, 0.833, 0.833], "y": [1, 1, 1]}, "o": {"x": [0.167, 0.167, 0.167], "y": [0, 0, 0]}, "t": 27, "s": [111, 111, 100]}, {"i": {"x": [0.833, 0.833, 0.833], "y": [1, 1, 1]}, "o": {"x": [0.167, 0.167, 0.167], "y": [0, 0, 0]}, "t": 36, "s": [101, 101, 100]}, {"t": 42.0000017106951, "s": [121, 121, 100]}], "ix": 6}}, "ao": 0, "ip": 0, "op": 300.00001221925, "st": 0, "bm": 0}, {"ddd": 0, "ind": 2, "ty": 4, "nm": "spark", "parent": 1, "sr": 1, "ks": {"o": {"a": 0, "k": 100, "ix": 11}, "r": {"a": 0, "k": 0, "ix": 10}, "p": {"a": 0, "k": [0, 0.5, 0], "ix": 2}, "a": {"a": 0, "k": [0, 0, 0], "ix": 1}, "s": {"a": 0, "k": [100, 100, 100], "ix": 6}}, "ao": 0, "shapes": [{"ty": "gr", "it": [{"ty": "rc", "d": 1, "s": {"a": 1, "k": [{"i": {"x": [0.667, 0.667], "y": [1, 1]}, "o": {"x": [0.333, 0.976], "y": [0, 0]}, "t": 35, "s": [2, 0]}, {"i": {"x": [0.667, 0.13], "y": [1, 1]}, "o": {"x": [0.333, 0.333], "y": [0, 0]}, "t": 42, "s": [2, 8]}, {"t": 53.0000021587343, "s": [1.633, 0]}], "ix": 2}, "p": {"a": 1, "k": [{"i": {"x": 0.667, "y": 1}, "o": {"x": 0.333, "y": 0}, "t": 35, "s": [0, -21], "to": [0, -1.5], "ti": [0, 1.5]}, {"t": 53.0000021587343, "s": [0, -30]}], "ix": 3}, "r": {"a": 0, "k": 0, "ix": 4}, "nm": "Rectangle Path 1", "mn": "ADBE Vector Shape - Rect", "hd": false}, {"ty": "fl", "c": {"a": 0, "k": [0.258823529412, 0.878431432387, 0.541176470588, 1], "ix": 4}, "o": {"a": 0, "k": 100, "ix": 5}, "r": 1, "bm": 0, "nm": "Fill 1", "mn": "ADBE Vector Graphic - Fill", "hd": false}, {"ty": "tr", "p": {"a": 0, "k": [0, -8], "ix": 2}, "a": {"a": 0, "k": [0, 0], "ix": 1}, "s": {"a": 0, "k": [100, 100], "ix": 3}, "r": {"a": 0, "k": 0, "ix": 6}, "o": {"a": 0, "k": 100, "ix": 7}, "sk": {"a": 0, "k": 0, "ix": 4}, "sa": {"a": 0, "k": 0, "ix": 5}, "nm": "Transform"}], "nm": "Rectangle 1", "np": 3, "cix": 2, "bm": 0, "ix": 1, "mn": "ADBE Vector Group", "hd": false}, {"ty": "rp", "c": {"a": 0, "k": 8, "ix": 1}, "o": {"a": 0, "k": 0, "ix": 2}, "m": 1, "ix": 2, "tr": {"ty": "tr", "p": {"a": 0, "k": [0, 0], "ix": 2}, "a": {"a": 0, "k": [0, 0], "ix": 1}, "s": {"a": 0, "k": [100, 100], "ix": 3}, "r": {"a": 0, "k": 45, "ix": 4}, "so": {"a": 0, "k": 100, "ix": 5}, "eo": {"a": 0, "k": 100, "ix": 6}, "nm": "Transform"}, "nm": "Repeater 1", "mn": "ADBE Vector Filter - Repeater", "hd": false}], "ip": 35.0000014255792, "op": 335.00001364483, "st": 35.0000014255792, "bm": 0}, {"ddd": 0, "ind": 3, "ty": 4, "nm": "check", "parent": 1, "sr": 1, "ks": {"o": {"a": 0, "k": 100, "ix": 11}, "r": {"a": 0, "k": 0, "ix": 10}, "p": {"a": 0, "k": [0, 0, 0], "ix": 2}, "a": {"a": 0, "k": [0, 0, 0], "ix": 1}, "s": {"a": 0, "k": [100, 100, 100], "ix": 6}}, "ao": 0, "shapes": [{"ind": 0, "ty": "sh", "ix": 1, "ks": {"a": 0, "k": {"i": [[0, 0], [0, 0], [3.5, 3.75], [-12.973, 5.349], [-6.124, -9.992], [12.125, -7.431], [7.431, 12.125]], "o": [[0, 0], [0, 0], [-3.5, -3.75], [10.764, -2.941], [7.431, 12.125], [-12.125, 7.431], [-7.431, -12.125]], "v": [[15.25, -9.688], [-5.75, 10.062], [-16, 0.25], [-6.777, -24.849], [21.955, -13.456], [13.456, 21.955], [-21.955, 13.456]], "c": false}, "ix": 2}, "nm": "Path 1", "mn": "ADBE Vector Shape - Group", "hd": false}, {"ty": "tm", "s": {"a": 1, "k": [{"i": {"x": [0.363], "y": [1]}, "o": {"x": [0.742], "y": [0]}, "t": 17, "s": [100]}, {"t": 45.0000018328876, "s": [0]}], "ix": 1}, "e": {"a": 1, "k": [{"i": {"x": [0.351], "y": [1]}, "o": {"x": [0.714], "y": [0]}, "t": 10, "s": [100]}, {"t": 40.0000016292334, "s": [23]}], "ix": 2}, "o": {"a": 0, "k": 0, "ix": 3}, "m": 1, "ix": 2, "nm": "Trim Paths 1", "mn": "ADBE Vector Filter - Trim", "hd": false}, {"ty": "st", "c": {"a": 0, "k": [0.260781411564, 0.878829656863, 0.541459326651, 1], "ix": 3}, "o": {"a": 0, "k": 100, "ix": 4}, "w": {"a": 0, "k": 4, "ix": 5}, "lc": 1, "lj": 1, "ml": 4, "bm": 0, "nm": "Stroke 1", "mn": "ADBE Vector Graphic - Stroke", "hd": false}], "ip": 22.0000008960784, "op": 310.000012626559, "st": 10.0000004073083, "bm": 0}, {"ddd": 0, "ind": 4, "ty": 4, "nm": "circle", "parent": 1, "sr": 1, "ks": {"o": {"a": 0, "k": 100, "ix": 11}, "r": {"a": 0, "k": 0, "ix": 10}, "p": {"a": 0, "k": [0, 0, 0], "ix": 2}, "a": {"a": 0, "k": [0, 0, 0], "ix": 1}, "s": {"a": 0, "k": [100, 100, 100], "ix": 6}}, "ao": 0, "shapes": [{"ind": 0, "ty": "sh", "ix": 1, "ks": {"a": 0, "k": {"i": [[-14.221, 0], [0, -14.221], [14.221, 0], [0, 14.221]], "o": [[14.221, 0], [0, 14.221], [-14.221, 0], [0, -14.221]], "v": [[0, -25.75], [25.75, 0], [0, 25.75], [-25.75, 0]], "c": true}, "ix": 2}, "nm": "Path 1", "mn": "ADBE Vector Shape - Group", "hd": false}, {"ty": "st", "c": {"a": 0, "k": [0.260781411564, 0.878829656863, 0.541459326651, 1], "ix": 3}, "o": {"a": 0, "k": 100, "ix": 4}, "w": {"a": 0, "k": 4, "ix": 5}, "lc": 1, "lj": 1, "ml": 4, "bm": 0, "nm": "Stroke 1", "mn": "ADBE Vector Graphic - Stroke", "hd": false}, {"ty": "tm", "s": {"a": 1, "k": [{"i": {"x": [0.363], "y": [1]}, "o": {"x": [0.742], "y": [0]}, "t": 7, "s": [100]}, {"t": 33.0000013441176, "s": [0]}], "ix": 1}, "e": {"a": 1, "k": [{"i": {"x": [0.351], "y": [1]}, "o": {"x": [0.714], "y": [0]}, "t": 0, "s": [100]}, {"t": 30.0000012219251, "s": [100]}], "ix": 2}, "o": {"a": 0, "k": 0, "ix": 3}, "m": 1, "ix": 3, "nm": "Trim Paths 1", "mn": "ADBE Vector Filter - Trim", "hd": false}], "ip": 0, "op": 300.00001221925, "st": 0, "bm": 0}], "markers": []}
\ No newline at end of file
diff --git a/app/src/main/assets/privacy_cn.html b/app/src/main/assets/privacy_cn.html
new file mode 100644
index 0000000..886b6a9
--- /dev/null
+++ b/app/src/main/assets/privacy_cn.html
@@ -0,0 +1,469 @@
+
+
+
˽ܶƼ˾ļΪܶƼ˾ǡ)öַʽռʹͨƽ̨ύûϢͣݣƷɼûϢͣݡܶƼȷϸİȫܱûͬ⣬ܶƼй¶κθϢͣϣĵ3СȨ⡣
+
+
˾ǿҽûϸĶ˽Ա˽Ȿ˾ûܶƼƽ̨ṩĸϢݼʹܶƼƷϱϢͣݵߺʵӦá˽עͷעûҵΪҪʱɲڸ¡ݡĺİ汾һЧûԱ˽κʻǣµܶƼѯ绰0755-86352225
+
+
Ա˽ߵ飬ֹͣʹܶƼķͲƷʹܶƼķͲƷʾܱ˽и˽߹ɡʹһֲԼ
+
+
ܶƼȨκʱı˽ߣڹ֮ʱЧ
+
+
һռϢͣ
+
+
(1ܶƼռ洢κûṩǻʹõϢͣݡõϢͣݿܰڣûʹܶƼƷύФԱաߡءֻ롢ַʵַϵϢ罻ýϢЧ֤ͼͥԱϵȸϣԼп֧ƽ̨ϣҪ
+
+
(2ܶƼԶռ洢ûǽлʹǵķͲƷʱϢͣݡûʹܶƼͲƷܱɼģӲϢϵͳ͡豸ʶ IP ַ MAC ַ GPS λáݡ˶ݡΪƫáճݡ֡ͼƬӰϢͣݡ
+
+
(3ܶƼվý塢ƽ̨ƶӦԼƷ)ӻͨܶƼƽ̨ͲƷšԱȣлϢͣݶܱռǿܽͨܶƼƽ̨ṩǵĻռϢͣݽϣܰڣܶƼ̡ƷӦóϢͣݡϢͣݽᱻΪϣֻҪϱֹ״̬
+
+
(4ͬңܶضƽ̨Ӧƣϸڹңع涨δ18֤꣬ȡ˵ͬʹܶƼķͲƷͬⱾ˽ߡ
+
+
ʹϢͣ
+
+
ܶƼȷϸİȫܱϷʹռ洢ϢͣݣϢͣݿܱʹڣ
+
+
(1ΪṩܶƼķͲƷ(2ĽάܶƼķͲƷ飬ڷûΪơ
+
+
(3)ܶƼķƷͻԼĿйͨ
+
+
(4ɣṩƷʾϢ
+
+
(5ͳϢͣݲͲƷʹԹ˾˾뱾˾ֱӻӿƹϵشӰϵҵڲʹá
+
+
Ȩ
+
+
һ˵ΪҪάֺܶƼķͲƷὫϢͣṩܶƼ˾ڲԱԱΪûṩȻ£ǿܻὫϢͣݴݸ
+
+
(1ڱܵ£ǿܻὫϢͣ¶ͣתκα˾ȨĵӦ̻ⲿӦ̣ԴٽṩķһЩ˾ڵҺй֮Ĺң֪Ϥͬ⣬ݱɿܲŷˡһݱ
+
+
(2ǿܽϢܶƼķṩԱ㿪չǵҵϢͣ¶ͣתܶƼȨκδ˻˾˾ȨʹøõϺͣݡǽɷ书ĸϢͣݣҲΪĿĶʹá
+
+
(3ǿܻйϽȨ˾ŵշҪΪִǵΪǻ˵ȨƲͣȫ¶ϢͣݡǿܹϢֹͣǷʹܶƼķͲƷΥʹΪԵϽзɿ硣
+
+
(4ǿǽзթϢռ͵ְȨ˾عϢ˾ԺϵķɳбҪṩ
+
+
(5ͨܶƼͲƷռĸϢͣݿܶƼ˾֮תƻ档ʹܶƼķͲƷΪͬⲢȨܶƼ¶תĸϢͣݡ
+
+
(6ϢΪܶƼȫʲۡתáתǽͨʾ֪ͨͨŷ֪ͨ
+
+
ġϢͣ
+
+
(1ʹܶƼضķʱͬһЩϢܰûڳкͷͼƬ
+
+
(2ͬϢͣݣҪ˽á
+
+
(3ѡϢͣͨܶƼƽ̨ƽ̨Ķƽ̨˽ߣǶƽ̨ϢͣݵİȫԲκΡ
+
+
(4ͬdzƹ㱾˾ƷĿĿܻʹϢͣݡ
+
+
塢Ϣͣ
+
+
(1ϢͣݵİȫǷdzҪܶƼȷĸϢͣδȨĽӴʹöֱʩ֤ܺϢͣݰȫ
+
+
(2ѭϵҵϢͣݰȫȻڻ͵Ӵ洢ԣ֤ṩϢͣݰٷٰ֮ȫܡ
+
+
(3ͨرضϢͨѶʽϿӡرնλܵȣֹֹϢͣݵϴ˿ܵʹܶƼķͲƷǵһЩܿ
+
+
(4Ʊ˻¼ϢȨͣתʹ˻(5˾߽ײõ֧ƽ̨Դٽӽ
+
+
(6ͨ¼ܶƼӦóĻɾIJϢͣϣǰϢȻǹɼġ
+
+
(7ͨܶƼ˻κκǷͬ⡣÷ڣܶƼκλδȨʹ˻Ϣͣй¶Ϊ
+
+
(8סκιңͬǽϢͣתơʹܶƼݿܶƼݱ˽ռʹϢͣݡݷɹ涨ĸϢͣݽܶƼطͣúֱûʽҪǴݿɾϢͣݻֹܶƼӦóûʸ
+
+
ṩ߰ơSDK
+
+
Bugly(ѶBugly)
+
ܣ Ϊ˿ٶλӦòƷԭCrashCrash豸ͳ
+
ռϢͣCrashCrashϢ̶߳ջROM/RAM/SD/Ե״̬AppϢ汾豸ϢIMEI豸ʶ
+
+
˽ӣhttps://privacy.qq.com/document/preview/fc748b3d96224fdb825ea79e132c1a56
+
+
+
ٶȶλ
+
ܣ ʵֶλܣ
+
ռϢͣ豸ʶϢAndroid IDIDFAIDFVγϢϵͳϢϵͳ汾豸ƷƼͺš豸ãӦϢӦ
+
˽ӣhttps://lbs.baidu.com/index.php?title=openprivacy#service-page-anchor-0-0
+
+
+
ٶȵͼ
+
ܣ ڵͼʾ켣
+
ռϢͣ豸ʶϢAndroid IDIDFAIDFVγϢдֻô洢Ϣ
+
˽ӣhttps://lbs.baidu.com/index.php?title=openprivacy#service-page-anchor-0-1
+
+
+
QQ
+
ܣ QQȨ¼ͷ
+
ռϢͣ豸ʶϢAndroid IDIDFAIDFVϵͳϢڴ濨ȨӦбϢ
+
˽ӣhttps://wiki.connect.qq.com/qq%e4%ba%92%e8%81%94sdk%e9%9a%90%e7%a7%81%e4%bf%9d%e6%8a%a4%e5%a3%b0%e6%98%8e
+
+
+
+
ܣ Ȩ¼ͷ
+
ռϢͣ豸ʶϢAndroid IDIDFAIDFVϵͳϢڴ濨ȨӦбϢ
+
+
˽ӣhttps://support.weixin.qq.com/cgi-bin/mmsupportacctnodeweb-bin/pages/RYiYJkLOrQwu0nb8
+
+
+
mapbox
+
ܣ λ·߹滮
+
ռϢͣ豸ʶϢAndroid IDIDFAIDFVϵͳϢڴ濨Ȩ,γϢ
+
˽ӣhttps://www.mapbox.com/legal/privacy
+
+
+
ͳơ
+
ܣȡû豸ΨһʶûϢ
+
+
ռϢͣ豸ʶϢAndroid IDIMEIIDFAIDFV豸MACַϵͳϢѰװAPPϢдֻô洢Ϣ
+
˽ӣhttps://www.jiguang.cn/license/privacy
+
+
+
ߡ
+
+
ʹǵķͲƷԼɴ˲κ飬ܱ˽ԼʹԼ涨ʹܶƼͲƷĹ
+
+
+
лĶκʣµܶƼѯ绰0755-86352225
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/privacy_en.html b/app/src/main/assets/privacy_en.html
new file mode 100644
index 0000000..185be48
--- /dev/null
+++ b/app/src/main/assets/privacy_en.html
@@ -0,0 +1,72 @@
+
+
+
+
At ABBI PET INC, we respect and are committed to protecting your privacy. This Privacy Policy outlines how we collect, use, safeguard, and keep your information confidential when you use our mobile application ("App").
+
+
1. Information We Collect
+
+- Personal Information: When you create an account, we may collect personal information such as your name, email address, and phone number.
+- Pet Information: We collect information about your pets, including their name, age, breed, and weight, to provide tailored services.
+- Usage Data: We collect information on how you interact with our App, such as the features you use and the time spent on the App.
+- Device Information: We may collect information about the device you use to access the App, including the device type, operating system, and unique device identifiers.
+- Location Data: With your permission, we may collect and process information about your devices location and your pet's location to provide location-based services.
+
+
+
+
2. How We Use Your Information
+
+- To Provide and Improve Our Services: We use your information to operate and improve the App and our services.
+- To Communicate with You: We may use your information to send you updates, newsletters, marketing materials, and other information that may be of interest to you.
+- To Personalize Your Experience: We use your information to tailor the content and services we offer to better meet your needs and preferences.
+- To Ensure Security and Compliance: We use your information to ensure the security of our App and compliance with applicable laws and regulations.
+
+
+
+
3. Data Confidentiality and Security
+
+- Data Encryption: We use industry-standard encryption protocols to protect your personal information during transmission and storage.
+- Access Controls: Access to your personal information is restricted to authorized personnel only, and we implement strict access controls to prevent unauthorized access.
+- Data Minimization: We only collect and retain the minimum amount of personal information necessary to provide our services.
+- Regular Audits: We conduct regular security audits and assessments to ensure our data protection measures are up to date and effective.
+
+
4. Sharing Your Information
+
+- Service Providers: We may share your information with third-party service providers who perform services on our behalf, such as hosting, data analysis, and customer support. These service providers are contractually obligated to keep your information confidential and secure.
+- Legal Requirements: We may disclose your information if required by law or in response to a legal request.
+- Business Transfers: In the event of a merger, acquisition, or sale of all or a portion of our assets, your information may be transferred to the new owner, subject to the same data protection commitments.
+
+
+
5. Your Choices
+
+- Account Information: You can update or delete your account information through the App's settings.
+- Marketing Communications: You can opt-out of receiving marketing communications from us by following the unsubscribe instructions in those communications or by contacting us directly.
+- Location Data: You can disable location services through your device settings, but this may affect certain features of the App.
+
+
+
+
6. Security
+
+
We take reasonable measures to protect your information from unauthorized access, use, or disclosure. However, no method of transmission over the Internet or method of electronic storage is 100% secure.
+
+
7. Children's Privacy
+
+
Our App is not intended for use by children under the age of 13, and we do not knowingly collect personal information from children under 13. If we become aware that we have collected personal information from a child under 13, we will take steps to delete that information.
+
+
8. Changes to This Privacy Policy
+
+
We may update this Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy within the App. You are advised to review this Privacy Policy periodically for any changes.
+
+
9. Contact Us
+
If you have any questions about this Privacy Policy, please contact us at:
+
ABBI PET INC
+
10700 Richmond Ave Suite 143
+
Houston, TX 77042
+
Email: support@abbidot.com
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/subscription_terms_conditions_en.html b/app/src/main/assets/subscription_terms_conditions_en.html
new file mode 100644
index 0000000..90afc2a
--- /dev/null
+++ b/app/src/main/assets/subscription_terms_conditions_en.html
@@ -0,0 +1,24 @@
+
+
+
+
+
ABBIDOT Tracker Subscription Terms and Conditions
+
+
1.Subscription Plans Users can choose between Basic and Prime plans. Basic plan subscribers can upgrade to Prime at any time. Prime plan subscribers can't change to Basic plan.
+
+
2.Refund Policy Automatic Refund (Within 48 Hours): Full refund available if canceled within 48 hours of subscription. Processed automatically without manual review. Manual Refund (After 48 Hours): For subscriptions older than 48 hours but within 1 month, refunds require manual approval. Eligibility: Only applicable to annual (1-year) subscriptions. Refunds may be prorated based on usage. No Refund After 1 Month: Subscriptions active for over 1 month are non-refundable.
+
+
3.Pausing Subscription & Number Retention Users may pause their subscription. Number Retention: Paused numbers can be retained for up to 1 year. A small fee will apply for number retention during the pause period. Failure to reactivate within 1 year may result in number release.
+
+
4.Modifications ABBIDOT reserves the right to update these terms. Users will be notified of changes. By subscribing, you agree to these terms.
+
+
For support contact:
+
support@abbidot.com
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/terms_cn.html b/app/src/main/assets/terms_cn.html
new file mode 100644
index 0000000..ce380d0
--- /dev/null
+++ b/app/src/main/assets/terms_cn.html
@@ -0,0 +1,476 @@
+˳ABBIDOTɼʹ
лʹܶƼ˾ļܶƼ˾ǡIJƷͷʹܶƼķͲƷǰϸĶʹļơһʹܶƼIJƷעΪܶƼûȷΪʾͬⱾȫݡй۰̨סκιңرõرڱв˵ǻʵʱԸʾΪܶƼ֮ͷͲƷʹöľзԼЭ顣ǿܻʱЩݷشҽԹķʽ֪ı飬ֹͣʹܶƼķͲƷ֪ͨʹñ˾ṩķͲƷӦóƽ̨ͲƷ÷ɽֹΪѽ˸º
һ
δ18꣬ȡøĸ˵ͬʸʹܶƼķͲƷͬңܶضƽ̨Ӧƣϸڹңع涨18꣬עΪܶƼûϸ¹
(1ṩʵЧȷµĸϽעᡣ(2ίעܶƼƷ˻ΪעܶƼ˻
(3Ʊ˻¼ϢȨͣתʹ˻
(4κδʹܶƼƷ˻ͣܶƼṩķͲƷΪ֪ͨǡ
(5ͨܶƼƷ˻κκǷͬ⡣÷ڣܶƼκʧδȨʹ˻Ϊ
Ȩ
(1Զ⣬ܶƼƷڵݣı롢űơͼΡӰ֡¼¼¡űͼ廭ӦóܼݣΪܶƼȨʹõĵУȨ̱ꡢרɱڱȷ˵⣬ܶƼȨ
(2̱ꡢ־ۡװ磬ܶƼƺͱ־ƣΪܶƼСעͣɡͨʹܶƼķܶƼIJƷκ̱ꡢ־ۡװɻκȨ
(3ͬⲻɾκδܶƼƷػӡIJϵȨ
(4κȨȨƷݷΧڣܶƼ˵ġġתõġתɵġɳĽΪԤʹĿҽܶƼڹڷʡزʹôݵȨݣаκ̱֪ʶȨκȨȨдݽʹãֹҵ;
(5ܶƼලʹòκʱκɱɻݵķȨȨܶƼΥõܶƼ֪ʶȨɾκݵȨܶƼʹȨܶƼݰȨȨκȨķ
(6ͬܶƼܶƼصضʹȨ⣬δܶƼͬ⣬ʹáơ༭ء롢ۡƷκηʽκݣϷκݡδȨʹݿʹܵ»ָغʹܶƼԴ˲еκΡ
ܶƼӦóƽ̨ļƽ̨ϷϷ֡ƬƵۺݣ˻κδУͬܶƼɣ
(1ʾȨκݣܶƼκûƽ̨ݸ
(2ͬܶƼʱɾκηƽ̨ƽ̨صΥݣַФȨȨȨڰҵ;ڵκΥΪݣΥơġ롢ƷתɡַתõȨ
(3ѱɾݿѱתشܼܶƼƽ̨ظҪ÷ɾθϡ
(4ⷢܶƼƽ̨ϵݾڷDZܵĻṩܶƼõġǶҵġתõġתɵġ˰ġȫ緶ΧɡԲ֪ͨȷϵΪκĿʹƽ̨ϵݣڿƷԼĻĽʹƷ
ġûΪ淶
ܶƼΪרҵƽ̨߱罻ܣ˽Ⲣϸ¹
(1ܶƼȨɸѡලɾûIJݣûٱߡ֤ΥݵȨ
(2κΥġġġɧŵġɫġġӵġӵĻ˷еġǡĻΥ÷ɷݡӻκξΪ
(3κδӵȫɼȨݣгֻᵽκ
ɡ
(4κο˺ûΪûƬ绰ַ
Ϣ
(5κι桢ҵݣκεijͽҵܶƼȨ
(6ģ¡αװκ˻֯ܶƼԱ
(7ʹԶܶƼƽ̨ƷκԶץȡھƵݲɼ
(8κοܹܡȡ۸ƽ̨ȫϵͳ룬κοܸšơʹСɻƽ̨ܵݡ
塢ʾ
ܶƼվý塢ƽ̨ƶӦԼƷӻܹͨܶƼƽ̨лⲢʾܶƼϿɡලЧƵΪܶƼԵݡͬгеķա
(1ڹʹܶƼIJƷǰǿ漰зա(2ΪκݻյκϢӿ漰зա
(3ڻ͵ӲƷԣܶƼ֤ƽ̨ƷϵġġκδõĻûκкġ
(4ڻ͵ӲƷԣܶƼķͲƷκʽijŵڷƷȷԡԡʵԡɿԻijŵ
(5÷ڣܶƼ漰ͲƷԼͨƽ̨ȡûӴκƷб֤𣬰Ȩʵԡض;ԼȨԵı֤
(6÷ڣܶƼʹûʹ÷ͲƷĹܿܵκʧ˺еκΡ
(7÷ڣܶƼûĻκΪܵκʧ˺еκΡ
(8÷ڣܶƼûƽ̨ϵκݾеκ
Ρ
(9ܶƼûκû֮飬ȨоǷ롣
(10÷û涨ķΧڣʹܶƼķƷκʧи
(11ܶƼϣܳǵķͲƷǣDzκν֤
ߡֹ
(1ܶƼκʱ䲻ֹ֪ͨκܶƼӦóۼƻƷ
(2÷ɣܶƼԲеκεκʱκԭᡢֹֹ˻ɾĵκηݣʹȫַܡ
(3Ⲣͬ⣬ܶƼƽ̨ϷijЩݣڻҪлƽ̨ʾûݣʹʻֹԽʾȨ÷ɣɾصݡ
(4˻ֹֹͣʹܶƼķͲƷȻЧ
ˡ⳥
(1ܶƼϣǵķͲƷܶƼҲ뱣ɵκ
(2ͬ⳥Ϊ֮ṩ绤ʹܶƼԱ¡ԱȨ̼Ӧʹõݻƽ̨ͲƷʹáƽ̨ػƽ̨ûصΪκΥʹκηɻκεȨĻκηʽ֮صΡ⡢ʧü֧ʦѡΪļ̳ˡߡаˡƲ˺壬شȫ÷κʹƽ̨йصʧеܶƼκȨ
(3ܶƼκʹûʹܶƼƽ̨ͨƽ̨Ʒƽ̨ûΪϵϵģμܶƼμܶƼƽ̨ʹصκݡμκֱӵġӵġżȻġĽеΣκʧʧʹܶƼѾ֪ɴ
(4еʹܶƼͲƷȫΡʹܶƼͲƷݶΨһʩֹͣʹñͲƷʹøƽ̨ɵκʧܶƼ⳥β1Ԫҡ
š˾ϽȨ
й۰̨סκιңòͬ
(1ͬ⣬ܶƼλй½й½˾ϽܶƼйϽȨ
(2ͬ⣬ƽ̨˽ܶƼ֮κӦܵй½ķɹϽĶִкͽͼĽӦй½ķɡ
(3ܶƼͱݻִзκ飬˫ӦѺЭ̽Э̲ʱκһܶƼסصķԺϡ
ʮ涨
(1ͬܶƼڷķΧͨӷʽκ֪ͨЭ顢¶ͨžзЧ
(2ͬܶƼԲ֪ͨκʱκתڱµȨǷй涨⽫ӰڱµȨ
(3ͬеκβֱ϶ΪЧಿӦЧ
лĶκʣµܶƼѯ绰0755-86352225
\ No newline at end of file
diff --git a/app/src/main/assets/terms_en.html b/app/src/main/assets/terms_en.html
new file mode 100644
index 0000000..7870ac3
--- /dev/null
+++ b/app/src/main/assets/terms_en.html
@@ -0,0 +1,77 @@
+
+
+
+
+
1. Acceptance of Terms
+
+
By downloading, installing, and using the ABBIDOT mobile application ("App"), you agree to be bound by these Terms and Conditions ("Terms"). If you do not agree to these Terms, do not use the App.
+
+
+
+
2. Use of the App
+
+- Eligibility: You must be at least 13 years old to use the App. By using the App, you represent and warrant that you meet this eligibility requirement.
+- License: ABBI PET INC grants you a limited, non-exclusive, non-transferable, and revocable license to use the App for personal, non-commercial use only.
+- Restrictions: You agree not to:
+
+
+- Modify, reverse engineer, decompile, or disassemble the App.
+- Use the App for any unlawful purpose or in any way that could harm ABBI PET INC or its users.
+- Access or use the App to build a competing service or product.
+
+
+
+
+
3. Accounts and Security
+
+- Account Creation: To use certain features of the App, you may need to create an account. You agree to provide accurate and complete information during the registration process.
+- Account Security: You are responsible for maintaining the confidentiality of your account credentials and for all activities that occur under your account. You agree to notify ABBI PET INC immediately of any unauthorized use of your account.
+
+
4. Privacy
+
+
Your use of the App is also governed by our Privacy Policy, which is incorporated by reference into these Terms. Please review our Privacy Policy to understand our practices regarding your information.
+
+
5. User Content
+
+- Ownership: You retain ownership of any content you submit or post through the App ("User Content"). By submitting User Content, you grant ABBI PET INC a worldwide, non-exclusive, royalty-free license to use, reproduce, distribute, and display your User Content in connection with the App.
+- Responsibility: You are solely responsible for your User Content. You agree not to post content that is illegal, harmful, or violates the rights of others.
+
+
+
+
6. Intellectual Property
+
+
All content, features, and functionality of the App, including but not limited to text, graphics, logos, and software, are the exclusive property of ABBI PET INC or its licensors and are protected by copyright, trademark, and other intellectual property laws.
+
+
7. Termination
+
+
ABBI PET INC may terminate or suspend your access to the App at any time, without prior notice or liability, for any reason, including if you breach these Terms. Upon termination, your right to use the App will immediately cease.
+
+
8. Disclaimers and Limitation of Liability
+
+- Disclaimers: The App is provided "as is" and "as available" without warranties of any kind, either express or implied. ABBI PET INC does not warrant that the App will be uninterrupted or error-free.
+- Limitation of Liability: To the maximum extent permitted by law, ABBI PET INC shall not be liable for any indirect, incidental, special, or consequential damages arising out of or in connection with your use of the App.
+
+
+
9. Governing Law
+
These Terms shall be governed by and construed in accordance with the laws of the State of Texas, without regard to its conflict of law principles.
+
+
10. Changes to Terms
+
ABBI PET INC reserves the right to modify these Terms at any time. We will notify you of any changes by posting the new Terms within the App. Your continued use of the App after the changes become effective constitutes your acceptance of the new Terms.
+
+
11. Data Confidentiality
+
We are committed to maintaining the confidentiality of your data. We employ the following measures to ensure data protection:
+
+- Confidentiality Agreements: All employees and third-party service providers who have access to your data are required to sign confidentiality agreements.
+- Data Anonymization: Where possible, we anonymize your data to protect your privacy.
+- Data Retention Policy: We retain your data only as long as necessary for the purposes outlined in our Privacy Policy, after which it is securely deleted or anonymized.
+
+
+
12. Contact Us
+
If you have any questions about these Terms, please contact us at:
+
ABBI PET INC
+
10700 Richmond Ave Suite 143
+
Houston, TX 77042
+
Email: support@abbidot.com
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/MyApplication.kt b/app/src/main/java/com/abbidot/tracker/MyApplication.kt
new file mode 100644
index 0000000..933dcdd
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/MyApplication.kt
@@ -0,0 +1,94 @@
+package com.abbidot.tracker
+
+import android.app.ActivityManager
+import android.app.Application
+import android.os.Build
+import android.os.Process
+import androidx.appcompat.app.AppCompatDelegate
+import coil.Coil
+import coil.ImageLoader
+import coil.decode.GifDecoder
+import coil.decode.ImageDecoderDecoder
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.baselibrary.util.MMKVUtil
+import com.hjq.toast.Toaster
+import com.qmuiteam.qmui.arch.QMUISwipeBackActivityManager
+import dagger.hilt.android.HiltAndroidApp
+
+
+/**
+ *Created by .yzq on 2021/11/2/002.
+ * @link
+ * @description:Application
+ */
+@HiltAndroidApp
+class MyApplication : Application() {
+
+ companion object {
+ lateinit var instance: Application
+ }
+
+ override fun onCreate() {
+ super.onCreate()
+ //强制浅色模式,使用 AppCompatDelegate 或 MaterialComponents 动态切换主题
+ AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
+ initInMainProcess {
+ instance = this
+ AppUtils.syncIsDebug(applicationContext)
+ QMUISwipeBackActivityManager.init(this)
+ MMKVUtil.init(this)
+
+ // 初始化 Toast 框架
+ Toaster.init(this)
+ Toaster.setView(R.layout.toast_my_layout)
+
+// JPushInterface.setDebugMode(true)
+// JPushInterface.init(this)
+
+// if (!AppUtils.isDebug()) {
+// //腾讯bugly初始化
+// CrashReport.initCrashReport(applicationContext, "06fc0a9cd1", AppUtils.isDebug())
+// }
+
+// //同意协议
+// SDKInitializer.setAgreePrivacy(this, true)
+//// LocationClient.setAgreePrivacy(true);
+// //在使用SDK各组件之前初始化context信息,传入ApplicationContext
+// SDKInitializer.initialize(this)
+// //自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.
+// //包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。
+// SDKInitializer.setCoordType(CoordType.GCJ02)
+
+// if (!AppUtils.isChina()) {
+// MapboxSearchSdk.initialize(application = this,
+// accessToken = getString(R.string.mapbox_access_token),
+// locationEngine = LocationEngineProvider.getBestLocationEngine(this))
+// }
+
+ //设置支持加载gif
+ val imageLoader = ImageLoader.Builder(this).componentRegistry {
+ if (Build.VERSION.SDK_INT >= 28) {
+ add(ImageDecoderDecoder(this@MyApplication))
+ } else {
+ add(GifDecoder())
+ }
+ }.build()
+ //设置全局唯一实例
+ Coil.setImageLoader(imageLoader)
+ }
+ }
+
+ /**
+ * 主进程初始化
+ */
+ private fun initInMainProcess(block: () -> Unit) {
+ val activityManager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
+ val myPId = Process.myPid()
+ val mainProcessName = packageName
+ activityManager.runningAppProcesses.forEach {
+ if (it.pid == myPId && it.processName == mainProcessName) {
+ block()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/AssignOptionsAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/AssignOptionsAdapter.kt
new file mode 100644
index 0000000..9807e18
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/AssignOptionsAdapter.kt
@@ -0,0 +1,47 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import coil.load
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.util.ViewUtil
+
+/**
+ *Created by .yzq on 2024/5/30/030.
+ * @link
+ * @description:
+ */
+class AssignOptionsAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_bottom_sheet_add_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val circleImageView = holder!!.getImageView(R.id.il_bottom_sheet_circle_image)
+ val wrapImageView = holder.getImageView(R.id.il_bottom_sheet_wrap_image)
+ val name = holder.getTextView(R.id.tv_bottom_sheet_name)
+
+ name.text = item.name
+ if (position == 0) {
+ circleImageView.visibility = View.GONE
+ wrapImageView.visibility = View.GONE
+ } else {
+ //处理设备类型
+ if (item.menuType == ConstantInt.SpecialType) {
+ wrapImageView.visibility = View.VISIBLE
+ circleImageView.visibility = View.GONE
+ wrapImageView.load(R.drawable.icon_tracker_device_small)
+ } else {
+ circleImageView.visibility = View.VISIBLE
+ wrapImageView.visibility = View.GONE
+ ViewUtil.instance.setPetTypeHead(circleImageView, item.value, item.menuType)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/BaiduMapPoiSearchResultAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/BaiduMapPoiSearchResultAdapter.kt
new file mode 100644
index 0000000..e9c700f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/BaiduMapPoiSearchResultAdapter.kt
@@ -0,0 +1,24 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.baidu.mapapi.search.core.PoiInfo
+
+/**
+ *Created by .yzq on 2022/7/4/004.
+ * @link
+ * @description:百度地图搜索地址返回结果
+ */
+class BaiduMapPoiSearchResultAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_baidu_map_poi_result
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: PoiInfo) {
+ holder!!.setText(R.id.baidu_map_poi_name, item.name)
+ holder.setText(R.id.baidu_map_poi_address, item.address)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/ChangePetListDialogAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/ChangePetListDialogAdapter.kt
new file mode 100644
index 0000000..6ecb0bd
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/ChangePetListDialogAdapter.kt
@@ -0,0 +1,90 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.content.Intent
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.PetBean
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.ui.activity.pet.PetProfileActivity
+import com.abbidot.tracker.util.ViewUtil
+import com.abbidot.tracker.widget.TypefaceRoundButton
+
+/**
+ *Created by .yzq on 2022/1/8/008.
+ * @link
+ * @description:切换宠物列表弹窗适配器
+ */
+class ChangePetListDialogAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+
+ private var mOnChangeClickListener: OnChangeClickListener? = null
+
+ //选中的宠物下标
+ private var mSelectPetPos = 0
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_my_pet_dialog
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: PetBean) {
+ val current =
+ holder!!.itemView.findViewById(R.id.dialog_my_pet_current_btn)
+ val change =
+ holder.itemView.findViewById(R.id.dialog_my_pet_change_btn)
+
+ holder.setText(R.id.dialog_my_pet_name, item.petName)
+
+ holder.getImageView(R.id.dialog_my_pet_head).apply {
+ ViewUtil.instance.setPetTypeHead(this, item.imgurl, item.petType)
+ setOnClickListener {
+ if (null != mOnChangeClickListener) {
+ mOnChangeClickListener!!.onCurrentClick()
+ }
+ val intent = Intent(mContext, PetProfileActivity::class.java)
+ intent.putExtra(ConstantString.Edit, true)
+ intent.putExtra(ConstantString.Pet, item)
+ mContext.startActivity(intent)
+ }
+ }
+
+ if (position == mSelectPetPos) {
+ current.visibility = View.VISIBLE
+ change.visibility = View.GONE
+ } else {
+ current.visibility = View.GONE
+ change.visibility = View.VISIBLE
+ }
+
+ current.setChangeAlphaWhenPress(true)
+ current.setOnClickListener {
+ if (null != mOnChangeClickListener) {
+ mOnChangeClickListener!!.onCurrentClick()
+ }
+ }
+
+ change.setChangeAlphaWhenPress(true)
+ change.setOnClickListener {
+ mSelectPetPos = position
+ notifyItemRangeChanged(0, getData().size)
+ if (null != mOnChangeClickListener) {
+ mOnChangeClickListener!!.onChangeClick(position)
+ }
+ }
+ }
+
+ fun setSelectPetPos(position: Int) {
+ mSelectPetPos = position
+ }
+
+ fun setOnChangeClickListener(onChangeClickListener: OnChangeClickListener) {
+ mOnChangeClickListener = onChangeClickListener
+ }
+
+ interface OnChangeClickListener {
+ fun onCurrentClick()
+ fun onChangeClick(position: Int)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/ChoosePlanAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/ChoosePlanAdapter.kt
new file mode 100644
index 0000000..e9ea3f1
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/ChoosePlanAdapter.kt
@@ -0,0 +1,82 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.graphics.Paint
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.PackageBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+
+/**
+ *Created by .yzq on 2024/8/6/006.
+ * @link
+ * @description:
+ */
+class ChoosePlanAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_choose_plan_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: PackageBean) {
+ holder?.apply {
+ getView(R.id.rl_choose_plan_shade_item).let {
+ if (item.selected) it.setBackgroundResource(R.drawable.shape20_yellow_border_cyan_bg)
+ else it.setBackgroundResource(0)
+ }
+
+ setText(R.id.tv_choose_plan_item_name, item.planName)
+
+ val price = if (item.discountedPrice > 0) item.discountedPrice else item.planPrice
+ getTextView(R.id.tv_choose_plan_item_money).apply {
+ text = if (item.mealUnit == ConstantString.PackageUnitMonth) {
+ String.format(
+ mContext.getString(R.string.txt_money_unit), Utils.formatDecimal(price, 2)
+ )
+ } else {
+ val monthPrice = Utils.formatDecimal(price / (item.period * 12), 2)
+ String.format(mContext.getString(R.string.txt_money_unit), monthPrice)
+ }
+ }
+
+ getTextView(R.id.tv_choose_plan_item_year_money).let {
+ it.text = String.format(
+ mContext.getString(R.string.txt_money_unit),
+ Utils.formatDecimal(item.discountedPrice, 2)
+ )
+
+ it.visibility = if (item.discount > 0) View.VISIBLE
+ else View.GONE
+ }
+
+ getTextView(R.id.tv_choose_plan_item_discount_money).let {
+ it.text = String.format(
+ mContext.getString(R.string.txt_money_unit),
+ Utils.formatDecimal(item.planPrice, 2)
+ )
+ it.paint.flags = Paint.STRIKE_THRU_TEXT_FLAG
+ it.visibility = if (item.discount > 0) View.VISIBLE
+ else View.GONE
+ }
+
+
+ getView(R.id.ll_choose_plan_item_discount_percent).let {
+ it.visibility = if (item.discount > 0) View.VISIBLE
+ else View.GONE
+ }
+ getTextView(R.id.tv_choose_plan_item_discount_percent).let {
+ it.text = "${item.discount}%"
+ }
+
+ getView(R.id.cv_choose_plan_item_popular).let {
+ if (item.popularType == ConstantInt.Type1) it.visibility = View.VISIBLE
+ else it.visibility = View.GONE
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/CreditCardAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/CreditCardAdapter.kt
new file mode 100644
index 0000000..88da45d
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/CreditCardAdapter.kt
@@ -0,0 +1,53 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import android.widget.RelativeLayout
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.CreditCardBean
+import com.abbidot.tracker.ui.activity.subscribe.PaymentMethodActivity
+import com.abbidot.tracker.ui.fragment.subscribe.CreditCardPaymentFragment
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.widget.TypefaceRoundButton
+
+/**
+ *Created by .yzq on 2024/3/21/021.
+ * @link
+ * @description:
+ */
+class CreditCardAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = R.layout.layout_credit_card_no_data
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_credit_card_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: CreditCardBean) {
+ val relativeLayout = holder!!.itemView as RelativeLayout
+ val primary = holder.getView(R.id.rb_credit_card_primary_item) as TypefaceRoundButton
+ if (item.checked) {
+ relativeLayout.setBackgroundResource(R.drawable.shape8_dark_border_pale_yellow_bg)
+ } else {
+ relativeLayout.setBackgroundResource(R.drawable.shape8_dark_gray_border_white_yellow_bg)
+ }
+ primary.visibility = if (item.isPrimary) View.VISIBLE else View.GONE
+ holder.getTextView(R.id.tv_credit_card_number_item).apply {
+ val formatCardNumber = Util.formatCardNumber(item.cardNumber)
+ val cardLogoImageId = Util.getCreditCardType(item.cardNumber)
+ text = formatCardNumber
+ if (cardLogoImageId == 0) setCompoundDrawablesWithIntrinsicBounds(
+ 0, 0, 0, 0
+ )
+ else setCompoundDrawablesWithIntrinsicBounds(
+ cardLogoImageId, 0, 0, 0
+ )
+ }
+ holder.getView(R.id.iv_credit_card_edit_btn).setOnClickListener {
+ (((mContext as PaymentMethodActivity).mFragments[0]) as CreditCardPaymentFragment).goEditCard(
+ item
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/DFUStateAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/DFUStateAdapter.kt
new file mode 100644
index 0000000..8c49e2f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/DFUStateAdapter.kt
@@ -0,0 +1,39 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DFUStateBean
+
+/**
+ *Created by .yzq on 2023/4/17/017.
+ * @link
+ * @description:
+ */
+class DFUStateAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_tracker_dfu_state
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DFUStateBean) {
+ val textView = holder!!.getTextView(R.id.item_dfu_state_name)
+ val stateName = if (item.progress in 1..100) {
+ "${item.stateName}${item.progress}%"
+ } else {
+ item.stateName
+ }
+ textView.text = stateName
+
+ if (position == getData().size - 1) {
+ holder.getView(R.id.item_dfu_state_progress).visibility = View.VISIBLE
+ holder.getView(R.id.item_dfu_state_ok).visibility = View.GONE
+ } else {
+ holder.getView(R.id.item_dfu_state_progress).visibility = View.GONE
+ holder.getView(R.id.item_dfu_state_ok).visibility = View.VISIBLE
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/DurationSetAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/DurationSetAdapter.kt
new file mode 100644
index 0000000..dfa8001
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/DurationSetAdapter.kt
@@ -0,0 +1,52 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.appcompat.widget.AppCompatCheckBox
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.abbidot.tracker.ui.activity.device.set.LiveDurationSetActivity
+import com.abbidot.tracker.ui.activity.device.set.TrackingDurationSetActivity
+
+/**
+ *Created by .yzq on 2024/6/7/007.
+ * @link
+ * @description:
+ */
+class DurationSetAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private var mTrackingDurationSetActivity: TrackingDurationSetActivity? = null
+ private var mLiveDurationSetActivity: LiveDurationSetActivity? = null
+
+ init {
+ if (ctx is TrackingDurationSetActivity) {
+ mTrackingDurationSetActivity = ctx
+ } else if (ctx is LiveDurationSetActivity) {
+ mLiveDurationSetActivity = ctx
+ }
+ }
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_duration_set_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ holder!!.setText(R.id.tv_duration_name_item, item.name)
+ val checkBox = holder.getView(R.id.cb_duration_set_check) as AppCompatCheckBox
+ checkBox.apply {
+ isChecked = item.selected
+ setOnCheckedChangeListener(null)
+ setOnClickListener {
+ isChecked = item.selected
+ if (mContext is TrackingDurationSetActivity) {
+ mTrackingDurationSetActivity?.setTrackingDuration(position)
+ } else if (mContext is LiveDurationSetActivity) {
+ mLiveDurationSetActivity?.setLiveDuration(position)
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/FamilyAvatarAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/FamilyAvatarAdapter.kt
new file mode 100644
index 0000000..47db29f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/FamilyAvatarAdapter.kt
@@ -0,0 +1,38 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.qmuiteam.qmui.widget.QMUIRadiusImageView
+
+/**
+ *Created by .yzq on 2024/2/22/022.
+ * @link
+ * @description:
+ */
+class FamilyAvatarAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_invite_family_avatar_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val qMUIRadiusImageView =
+ holder!!.getView(R.id.il_invite_family_avatar_layout) as QMUIRadiusImageView
+ qMUIRadiusImageView.apply {
+ setImageResource(item.imageId)
+ borderColor = ContextCompat.getColor(mContext, R.color.select_color)
+ borderWidth = if (item.selected) {
+ AppUtils.dpToPx(2)
+ } else {
+ AppUtils.dpToPx(0)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/FamilyMembersAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/FamilyMembersAdapter.kt
new file mode 100644
index 0000000..a6ffd9d
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/FamilyMembersAdapter.kt
@@ -0,0 +1,63 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.FamilyBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.ui.activity.pet.FamilyMembersActivity
+import com.qmuiteam.qmui.layout.QMUIButton
+
+/**
+ *Created by .yzq on 2024/2/21/021.
+ * @link
+ * @description:
+ */
+class FamilyMembersAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val mFamilyMembersActivity: FamilyMembersActivity
+
+ init {
+ mFamilyMembersActivity = ctx as FamilyMembersActivity
+ }
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_family_member_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: FamilyBean) {
+ val activeState = holder!!.getView(R.id.tv_family_member_active_state)
+ val pendingState = holder.getView(R.id.tv_family_member_pending_state)
+ val resendBtn = holder.getView(R.id.btn_family_member_resend) as QMUIButton
+ val avatarImageView = holder.getImageView(R.id.il_family_member_head)
+ resendBtn.setChangeAlphaWhenPress(true)
+ if (item.status == ConstantInt.Open) {
+ activeState.visibility = View.VISIBLE
+ pendingState.visibility = View.GONE
+ resendBtn.visibility = View.GONE
+ } else {
+ activeState.visibility = View.INVISIBLE
+ pendingState.visibility = View.VISIBLE
+ resendBtn.visibility = View.VISIBLE
+ }
+ holder.setText(R.id.tv_family_member_email, item.acceptEmail)
+
+ val avatarImageResId = if (item.avatar == ConstantInt.Man) {
+ R.drawable.icon_family_boy_avatar
+ } else {
+ R.drawable.icon_family_girl_avatar
+ }
+ avatarImageView.setImageResource(avatarImageResId)
+
+ holder.setClickListener(R.id.iv_delete_family_member_btn, View.OnClickListener {
+ mFamilyMembersActivity.deleteFamily(item)
+ })
+ resendBtn.setOnClickListener {
+ mFamilyMembersActivity.resendFamily(item)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/FamilyRelationAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/FamilyRelationAdapter.kt
new file mode 100644
index 0000000..c6458b0
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/FamilyRelationAdapter.kt
@@ -0,0 +1,26 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+
+/**
+ *Created by .yzq on 2024/2/22/022.
+ * @link
+ * @description:
+ */
+class FamilyRelationAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_invite_family_relation_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ holder!!.setText(R.id.tv_invite_family_relation_text, item.name)
+ holder.itemView.isSelected = item.selected
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/FeedbackImageAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/FeedbackImageAdapter.kt
new file mode 100644
index 0000000..c52c591
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/FeedbackImageAdapter.kt
@@ -0,0 +1,53 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.text.TextUtils
+import android.view.View
+import androidx.fragment.app.FragmentActivity
+import coil.load
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.ui.activity.help.FeedbackActivity
+import java.io.File
+
+/**
+ *Created by .yzq on 2022/3/23/023.
+ * @link
+ * @description:反馈上传的图片
+ */
+class FeedbackImageAdapter(
+ ctx: Context, activity: FragmentActivity, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val mActivity = activity as FeedbackActivity
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_feedback_image
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: MenuTxtBean) {
+ val imageView = holder!!.getImageView(R.id.show_select_image)
+ val deleteView = holder.getTextView(R.id.delete_image_cancel)
+ if (TextUtils.isEmpty(item.imageUrl)) {
+ imageView.load(R.drawable.ico_photo)
+ deleteView.visibility = View.GONE
+ imageView.setOnClickListener {
+// ViewUtil.instance.goSelectPhoto(
+// mActivity,
+// ResultCode.ResultCode_1,
+// count = mActivity.mLimitPhotoCount - (getData().size - 1)
+// )
+ }
+ } else {
+ imageView.setOnClickListener(null)
+ imageView.load(File(item.imageUrl))
+ deleteView.visibility = View.VISIBLE
+ deleteView.setOnClickListener {
+ val list = getData()
+ mActivity.deletePhoto(list, item)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/FencesZoneAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/FencesZoneAdapter.kt
new file mode 100644
index 0000000..115c58e
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/FencesZoneAdapter.kt
@@ -0,0 +1,74 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.content.res.ColorStateList
+import android.view.View
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.FencesBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.util.ViewUtil
+import com.abbidot.tracker.widget.TypefaceRoundButton
+
+/**
+ *
+ */
+class FencesZoneAdapter(
+ ctx: Context, list: MutableList?, isShowRightArrow: Boolean = true
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private var isShowRightArrow = true
+
+ init {
+ this.isShowRightArrow = isShowRightArrow
+ }
+
+ override fun getEmptyLayoutId(viewType: Int) = R.layout.layout_virtual_fences_empty_view
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_virtual_fences_layout
+
+ override fun noData(holder: RecyclerViewHolder?) {
+ holder?.apply {
+ getView(R.id.btn_empty_fences_add_safe_zone).visibility =
+ if (isShowNoDataAddButton) View.VISIBLE
+ else View.GONE
+ }
+ }
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: FencesBean) {
+ holder!!.getTextView(R.id.tv_virtual_fences_list_name).text = item.name
+ holder.getTextView(R.id.tv_virtual_fences_list_address).text = item.address
+
+ val fenceNameTypeImage = ViewUtil.instance.getFenceNameImageType(item.fenceNameType)
+
+ holder.getImageView(R.id.iv_virtual_fences_list_type).setImageResource(fenceNameTypeImage)
+
+ val typefaceButton =
+ holder.getView(R.id.tv_virtual_fences_list_switch_state) as TypefaceRoundButton
+ val switchText: String
+ val switchTextColor: Int
+ val switchStrokeColor = if (item.isOn == ConstantInt.Open) {
+ switchText = mContext.getString(R.string.txt_active)
+ switchTextColor = ContextCompat.getColor(mContext, R.color.green_color100)
+ ContextCompat.getColor(mContext, R.color.green_color100)
+ } else {
+ switchText = mContext.getString(R.string.txt_deactivate)
+ switchTextColor = ContextCompat.getColor(mContext, R.color.block_color2)
+ ContextCompat.getColor(mContext, R.color.white_gray_color1)
+ }
+ typefaceButton.apply {
+ text = switchText
+ setTextColor(switchTextColor)
+ setStrokeColors(ColorStateList.valueOf(switchStrokeColor))
+ }
+
+ if (isShowRightArrow) {
+ holder.getView(R.id.iv_virtual_fences_list_arrow_right).visibility = View.VISIBLE
+ } else {
+ holder.getView(R.id.iv_virtual_fences_list_arrow_right).visibility = View.INVISIBLE
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/FirstPermissionsAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/FirstPermissionsAdapter.kt
new file mode 100644
index 0000000..c9cb3ff
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/FirstPermissionsAdapter.kt
@@ -0,0 +1,81 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.ui.activity.set.FirstPermissionsActivity
+import com.abbidot.tracker.widget.TypefaceButton
+
+/**
+ *Created by .yzq on 2024/3/25/025.
+ * @link
+ * @description:
+ */
+class FirstPermissionsAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val mPermissionsActivity = ctx as FirstPermissionsActivity
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_permission_state_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val stateView = holder!!.getImageView(R.id.cb_permission_state_item)
+ val typefaceTextView = holder.getTextView(R.id.tv_permission_tip_item)
+ val btnLayout = holder.getView(R.id.ll_permission_set_layout)
+ val btnSkip = holder.getView(R.id.btn_permission_skip_set) as TypefaceButton
+ val btnEnable = holder.getView(R.id.btn_permission_enable_set) as TypefaceButton
+ btnSkip.setChangeAlphaWhenPress(true)
+ btnEnable.setChangeAlphaWhenPress(true)
+
+ if (item.selected) {
+ typefaceTextView.visibility = View.VISIBLE
+ holder.itemView.setBackgroundResource(R.drawable.shape16_white_color_bg)
+
+ if (item.state == ConstantInt.Type1) {
+ btnLayout.visibility = View.GONE
+ } else {
+ btnLayout.visibility = View.VISIBLE
+ }
+ } else {
+ btnLayout.visibility = View.GONE
+ typefaceTextView.visibility = View.GONE
+ holder.itemView.setBackgroundResource(R.drawable.shape10_white_bg)
+ }
+
+ when (item.state) {
+ ConstantInt.SpecialType -> stateView.setImageResource(R.drawable.icon_permission_error_check_svg)
+ ConstantInt.Type0 -> stateView.setImageResource(R.drawable.icon_permission_no_check_svg)
+ ConstantInt.Type1 -> stateView.setImageResource(R.drawable.icon_permission_check_svg)
+ }
+
+ holder.setText(R.id.tv_permission_name_item, item.name)
+ typefaceTextView.text = item.value
+
+ btnSkip.setOnClickListener {
+ item.state = ConstantInt.SpecialType
+ item.selected = false
+ notifyItemChanged(position)
+// if (position + 1 < getData().size) {
+// getData()[position + 1].
+// }
+ }
+ btnEnable.setOnClickListener {
+ when (position) {
+ 0 -> mPermissionsActivity.mPermissionsCommon.operateBluetooth()
+ 1 -> mPermissionsActivity.mPermissionsCommon.operateGPSLocation()
+ 2 -> mPermissionsActivity.mPermissionsCommon.operateNotifications(
+ this, ConstantInt.SpecialType
+ )
+ }
+ }
+
+ mPermissionsActivity.updateNextBtnState()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/GridItemDecoration.kt b/app/src/main/java/com/abbidot/tracker/adapter/GridItemDecoration.kt
new file mode 100644
index 0000000..7a1e683
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/GridItemDecoration.kt
@@ -0,0 +1,57 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.graphics.Rect
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+import com.qmuiteam.qmui.util.QMUIDisplayHelper
+
+/**
+ *Created by .
+ * @link https://blog.csdn.net/Lee465357793/article/details/130830127
+ * @description:RecyclerView GridLayoutManager item间距设置,两端对齐
+ * @param offset 控件的外边距,不使用屏幕宽度来计算
+ */
+class GridItemDecoration(
+ context: Context, spanCount: Int, private var itemWidth: Int, top: Int, bottom: Int, offset: Int
+) : RecyclerView.ItemDecoration() {
+
+ private var mSpanCount = spanCount
+ private val mContext = context
+ private var mColumnSpacing = 0
+ private val mTop = top
+ private val mBottom = bottom
+
+ private val rvWidth by lazy {
+ QMUIDisplayHelper.getScreenWidth(mContext) - offset
+ }
+
+ init {
+ mColumnSpacing = (rvWidth - (itemWidth * mSpanCount)) / (mSpanCount - 1)
+ }
+
+ fun updateSpaceCount(count: Int) {
+ mSpanCount = count
+ mColumnSpacing = (rvWidth - (itemWidth * mSpanCount)) / (mSpanCount - 1)
+ }
+
+ override fun getItemOffsets(
+ outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
+ ) {
+ // 获取view 在adapter中的位置。
+ val position = parent.getChildAdapterPosition(view)
+ // view 所在的列
+ val column = position % mSpanCount
+ // column * (列间距 * (1f / 列数))
+ outRect.left = (column * mColumnSpacing / mSpanCount)
+ // 列间距 - (column + 1) * (列间距 * (1f /列数))
+ outRect.right = (mColumnSpacing - (column + 1) * mColumnSpacing / mSpanCount)
+
+ if (mTop > 0) {
+ outRect.top = mTop
+ }
+ if (mBottom > 0) {
+ outRect.bottom = mBottom
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HelpTextImageTypeAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HelpTextImageTypeAdapter.kt
new file mode 100644
index 0000000..adef564
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/HelpTextImageTypeAdapter.kt
@@ -0,0 +1,73 @@
+package com.abbidot.tracker.adapter
+
+import android.graphics.Typeface
+import android.widget.ImageView
+import androidx.appcompat.widget.AppCompatImageView
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.constant.MultipleEntity
+import com.abbidot.tracker.widget.TypefaceTextView
+import com.chad.library.adapter.base.BaseMultiItemQuickAdapter
+import com.chad.library.adapter.base.viewholder.BaseViewHolder
+
+
+/**
+ *Created by .yzq on 2024/8/12/012.
+ * @link
+ * @description:
+ */
+class HelpTextImageTypeAdapter(list: MutableList?) :
+ BaseMultiItemQuickAdapter(list) {
+
+ init {
+ //加粗的标题文字
+ addItemType(MultipleEntity.TEXT, R.layout.layout_help_title1)
+ //只是图片的
+ addItemType(MultipleEntity.IMG, R.layout.layout_help_image)
+ //显示不同颜色的文字
+ addItemType(MultipleEntity.IMG_TEXT, R.layout.layout_help_title1)
+ //显示16sp大小的文字内容
+ addItemType(MultipleEntity.IMG_IMG, R.layout.layout_help_title1)
+ //显示14sp大小的文字内容
+ addItemType(MultipleEntity.IMG_TEXT_IMG, R.layout.layout_help_title2)
+ }
+
+ override fun convert(holder: BaseViewHolder, item: MenuTxtBean) {
+// val position = getItemPosition(item)
+ when (item.itemType) {
+ MultipleEntity.TEXT -> {
+ // 创建一个Typeface对象,指定加粗字体
+ val typefaceBold = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
+ holder.getView(R.id.tv_help_title_one).apply {
+ text = item.menuName
+ typeface = typefaceBold
+ }
+ holder.itemView.setPadding(0, AppUtils.dpToPx(8), 0, 0)
+ }
+
+ MultipleEntity.IMG_TEXT -> holder.getView(R.id.tv_help_title_one)
+ .apply {
+ text = item.menuName
+ setTextColor(ContextCompat.getColor(context, item.colorRedId))
+ }
+
+ MultipleEntity.IMG -> {
+ holder.getView(R.id.iv_help_image_type)
+ .setImageResource(item.imageId)
+ }
+
+ MultipleEntity.IMG_IMG -> {
+ holder.getView(R.id.tv_help_title_one).text = item.menuName
+ holder.itemView.setPadding(0, AppUtils.dpToPx(20), 0, 0)
+ }
+
+ MultipleEntity.IMG_TEXT_IMG -> {
+ holder.getView(R.id.tv_help_title_two).text = item.menuName
+ holder.itemView.setPadding(0, AppUtils.dpToPx(14), 0, 0)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HomeAccountMenuAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HomeAccountMenuAdapter.kt
new file mode 100644
index 0000000..9e44fd6
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/HomeAccountMenuAdapter.kt
@@ -0,0 +1,167 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Intent
+import android.text.TextUtils
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.RecyclerView
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseDialog
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.MultipleEntity
+import com.abbidot.tracker.ui.activity.HomeV2Activity
+import com.abbidot.tracker.ui.activity.help.FeedbackActivity
+import com.abbidot.tracker.ui.activity.help.HowWorkActivity
+import com.abbidot.tracker.ui.activity.set.AboutActivity
+import com.abbidot.tracker.ui.activity.set.AdvancedSetActivity
+import com.abbidot.tracker.ui.activity.set.NotificationsSetActivity
+import com.abbidot.tracker.ui.activity.set.PermissionsSetActivity
+import com.abbidot.tracker.ui.common.UnitSelectDialog
+import com.abbidot.tracker.ui.fragment.account.AccountV2Fragment
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.abbidot.tracker.widget.TypefaceTextView
+import com.chad.library.adapter.base.BaseMultiItemQuickAdapter
+import com.chad.library.adapter.base.viewholder.BaseViewHolder
+import com.qmuiteam.qmui.widget.grouplist.QMUICommonListItemView
+
+/**
+ *Created by .yzq on 2023/12/27/027.
+ * @link
+ * @description:
+ */
+class HomeAccountMenuAdapter(
+ accountV2Fragment: AccountV2Fragment, list: MutableList?
+) : BaseMultiItemQuickAdapter(list) {
+
+ private val mLogOutTipsType = 0
+ private val mClearCacheTipsType = 1
+ private val mCloseAccountTipsType = 2
+ private lateinit var mHomeV2Activity: HomeV2Activity
+ private lateinit var mUnitSelectDialog: UnitSelectDialog
+ private val mAccountV2Fragment = accountV2Fragment
+
+ init {
+ addItemType(MultipleEntity.TEXT, R.layout.item_title_text_type)
+ addItemType(MultipleEntity.IMG_TEXT, R.layout.item_qmui_common_item_view)
+ }
+
+ override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
+ super.onAttachedToRecyclerView(recyclerView)
+ mHomeV2Activity = context as HomeV2Activity
+ mUnitSelectDialog = UnitSelectDialog(context)
+ }
+
+ override fun convert(holder: BaseViewHolder, item: MenuTxtBean) {
+ val position = getItemPosition(item)
+ when (item.itemType) {
+ MultipleEntity.TEXT -> {
+ val typefaceTextView = holder.getView(R.id.tv_title_name)
+ typefaceTextView.text = item.menuName
+ }
+
+ MultipleEntity.IMG_TEXT -> {
+ holder.getView(R.id.tracker_manage_setting_item).run {
+ ViewUtil.instance.showQMUICommonListItemView(
+ context, this, {
+// Toaster.show("$position")
+ when (position) {
+ 1 -> mHomeV2Activity.startActivity(
+ Intent(
+ context, HowWorkActivity::class.java
+ )
+ )
+
+ 2 -> mHomeV2Activity.startActivity(
+ Intent(
+ context, FeedbackActivity::class.java
+ )
+ )
+
+ 4 -> mHomeV2Activity.startActivity(
+ Intent(
+ context, NotificationsSetActivity::class.java
+ )
+ )
+
+ 5 -> mUnitSelectDialog.showUnitDialog(object :
+ BaseDialog.OnDialogSelectListener {
+ override fun onSelectClick(dialog: BaseDialog<*>, any: Any) {
+ if (any is Int) {
+ val unit = any
+ val oldUnit = Util.getMeasureSpUnit()
+ if (unit == oldUnit) {
+ return
+ }
+ item.menuValue =
+ if (unit == ConstantInt.Type1) context.getString(R.string.txt_imperial)
+ else context.getString(R.string.txt_metric)
+ mAccountV2Fragment.setMeasureUnit(unit)
+ }
+ }
+ })
+// mHomeV2Activity.startActivity(
+// Intent(
+// context, FirstMeasurementUnitsActivity::class.java
+// )
+// )
+
+
+ 6 -> mHomeV2Activity.startActivity(
+ Intent(
+ context, PermissionsSetActivity::class.java
+ )
+ )
+
+ 7 -> mHomeV2Activity.startActivity(
+ Intent(
+ context, AdvancedSetActivity::class.java
+ )
+ )
+
+ 9 -> mHomeV2Activity.startActivity(
+ Intent(
+ context, AboutActivity::class.java
+ )
+ )
+
+ 10 -> dialogShowType(
+ mLogOutTipsType,
+ mHomeV2Activity.getString(R.string.txt_log_out_tips),
+ position
+ )
+
+ }
+ }, item.menuName
+ )
+ if (!TextUtils.isEmpty(item.menuValue)) {
+ detailText = item.menuValue
+ }
+ setImageDrawable(ContextCompat.getDrawable(context, item.imageId))
+ }
+ }
+ }
+ }
+
+ private fun dialogShowType(type: Int, string: String, pos: Int) {
+ ViewUtil.instance.showDialog(context, string, object : BaseDialog.OnDialogOkListener {
+ override fun onOkClick(dialog: BaseDialog<*>) {
+ dialog.dismiss()
+ when {
+ mLogOutTipsType == type -> {
+ Util.logOut(mHomeV2Activity, mHomeV2Activity.lifecycleScope)
+ }
+
+ mCloseAccountTipsType == type -> {
+// closeAccount()
+ }
+
+ else -> {
+// mHomeV2Activity.clearCache(this@HomeAccountMenuAdapter, pos)
+ }
+ }
+ }
+ }, okTextResId = R.string.txt_sure)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HomeMapDeviceMsgAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HomeMapDeviceMsgAdapter.kt
new file mode 100644
index 0000000..9375cd4
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/HomeMapDeviceMsgAdapter.kt
@@ -0,0 +1,32 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.widget.TypefaceButton
+
+/**
+ * 首页地图宠物警告适配器
+ */
+class HomeMapDeviceMsgAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_home_map_device_msg
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val typefaceTextView = holder!!.getView(R.id.tv_device_msg_content) as TypefaceButton
+ typefaceTextView.apply {
+ text = item.value
+ val colorId = if (item.state == ConstantInt.Type1) R.color.green_color10
+ else R.color.device_msg_color1
+
+ setBackgroundColor(ContextCompat.getColor(context, colorId))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HomeMapDeviceStateAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HomeMapDeviceStateAdapter.kt
new file mode 100644
index 0000000..136130c
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/HomeMapDeviceStateAdapter.kt
@@ -0,0 +1,70 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.text.TextUtils
+import android.view.View
+import androidx.appcompat.widget.AppCompatImageView
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.widget.BatteryView
+import com.abbidot.tracker.widget.TypefaceTextView
+
+/**
+ * 首页地图宠物警告适配器
+ */
+class HomeMapDeviceStateAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_home_map_device_state
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val typefaceTextView =
+ holder!!.getView(R.id.tv_home_map_device_name_item) as TypefaceTextView
+ val iv = holder.getView(R.id.iv_home_map_device_item) as AppCompatImageView
+ val bv = holder.getView(R.id.bv_home_map_device_power) as BatteryView
+ val ivState = holder.getView(R.id.iv_home_map_device_state_item) as AppCompatImageView
+ val detailTextView =
+ holder.getTextView(R.id.tv_map_device_state_detail_item) as TypefaceTextView
+
+ if (item.menuType == ConstantInt.Open) {
+ ivState.setImageResource(R.drawable.icon_map_online)
+ } else {
+ ivState.setImageResource(R.drawable.icon_map_offline)
+ }
+
+ if (item.imageId == 0) {
+ iv.visibility = View.GONE
+ bv.visibility = View.VISIBLE
+ bv.setValue(item.state)
+ } else {
+ iv.visibility = View.VISIBLE
+ bv.visibility = View.GONE
+ iv.setImageResource(item.imageId)
+ }
+
+ typefaceTextView.text = item.name
+ detailTextView.text = item.value
+
+ if (item.selected) {
+ detailTextView.visibility = View.VISIBLE
+ typefaceTextView.visibility = View.GONE
+ } else {
+ detailTextView.visibility = View.GONE
+ if (TextUtils.isEmpty(item.name)) {
+ typefaceTextView.visibility = View.GONE
+ } else {
+ typefaceTextView.visibility = View.VISIBLE
+ }
+ }
+
+ holder.itemView.setOnClickListener {
+ item.selected = !item.selected
+ notifyItemChanged(position)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HomePetFamilyAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HomePetFamilyAdapter.kt
new file mode 100644
index 0000000..e8e8a13
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/HomePetFamilyAdapter.kt
@@ -0,0 +1,34 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.FamilyBean
+import com.abbidot.tracker.constant.ConstantInt
+
+/**
+ *Created by .yzq on 2023/12/25/025.
+ * @link
+ * @description:
+ */
+class HomePetFamilyAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = R.layout.layout_family_empty_view
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_home_pet_family
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: FamilyBean) {
+ holder!!.setText(R.id.item_home_pet_family_name, item.acceptEmail)
+ val avatarImageView = holder.getImageView(R.id.item_home_pet_family_head)
+
+ val avatarImageResId = if (item.avatar == ConstantInt.Man) {
+ R.drawable.icon_family_boy_avatar
+ } else {
+ R.drawable.icon_family_girl_avatar
+ }
+ avatarImageView.setImageResource(avatarImageResId)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HomePetTrackMenuAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HomePetTrackMenuAdapter.kt
new file mode 100644
index 0000000..b262e80
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/HomePetTrackMenuAdapter.kt
@@ -0,0 +1,106 @@
+package com.abbidot.tracker.adapter
+
+import android.graphics.Typeface
+import android.view.LayoutInflater
+import android.view.View
+import androidx.appcompat.widget.AppCompatImageView
+import androidx.core.content.ContextCompat
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.MultipleEntity
+import com.abbidot.tracker.ui.activity.device.set.LedLightActivity
+import com.abbidot.tracker.ui.activity.device.set.LiveDurationSetActivity
+import com.abbidot.tracker.ui.activity.device.set.PowerOffActivity
+import com.abbidot.tracker.ui.activity.device.set.TrackingDurationSetActivity
+import com.abbidot.tracker.ui.fragment.device.HomeTrackFragment
+import com.abbidot.tracker.util.ViewUtil
+import com.abbidot.tracker.widget.TypefaceTextView
+import com.chad.library.adapter.base.BaseMultiItemQuickAdapter
+import com.chad.library.adapter.base.viewholder.BaseViewHolder
+import com.qmuiteam.qmui.widget.grouplist.QMUICommonListItemView
+
+/**
+ *
+ */
+class HomePetTrackMenuAdapter(
+ fragment: HomeTrackFragment, list: MutableList?
+) : BaseMultiItemQuickAdapter(list) {
+
+ private var mTypeface: Typeface
+ private var mHomeTrackFragment: HomeTrackFragment = fragment
+
+ init {
+ addItemType(MultipleEntity.TEXT, R.layout.item_qmui_common_item_view)
+ addItemType(MultipleEntity.IMG_TEXT, R.layout.item_qmui_common_item_view)
+ addItemType(MultipleEntity.TEXT_NAME, R.layout.item_qmui_common_item_view)
+ addItemType(MultipleEntity.IMG_TEXT_IMG, R.layout.item_qmui_common_item_view)
+ mTypeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
+ }
+
+ override fun convert(holder: BaseViewHolder, item: MenuTxtBean) {
+ val position = getItemPosition(item)
+ val qMUICommonItemView =
+ holder.getView(R.id.tracker_manage_setting_item).apply {
+ ViewUtil.instance.showQMUICommonListItemView(
+ context, this, null, item.menuName
+ )
+ background =
+ ContextCompat.getDrawable(context, R.drawable.selector_transparent_pressed)
+ }
+ qMUICommonItemView.textView.typeface = mTypeface
+ qMUICommonItemView.setOnClickListener {
+ when (position) {
+ 0 -> mHomeTrackFragment.goPetDataActivity(LedLightActivity::class.java)
+ 1 -> mHomeTrackFragment.goMapDeviceDataActivity(TrackingDurationSetActivity::class.java)
+ 2 -> mHomeTrackFragment.goMapDeviceDataActivity(LiveDurationSetActivity::class.java)
+ 3 -> mHomeTrackFragment.firmwareCheckUpdate()
+ 4 -> mHomeTrackFragment.goPetDataActivity(PowerOffActivity::class.java)
+ }
+ }
+
+ when (item.itemType) {
+ MultipleEntity.TEXT -> qMUICommonItemView.detailText = item.menuValue
+
+ MultipleEntity.IMG_TEXT -> {
+ }
+
+ MultipleEntity.TEXT_NAME -> {
+ qMUICommonItemView.accessoryType = QMUICommonListItemView.ACCESSORY_TYPE_SWITCH
+ qMUICommonItemView.detailText = ""
+ qMUICommonItemView.switch.apply {
+ isChecked = item.menuValue == ConstantInt.Open.toString()
+ isEnabled = isChecked
+ setOnClickListener {
+ if (!isChecked) {
+ //turnOff
+ mHomeTrackFragment.operateDeviceTips(R.string.txt_turnoff_tips, 0)
+ }
+ //屏蔽点击就变状态
+ isChecked = !isChecked
+ }
+ }
+ }
+
+ MultipleEntity.IMG_TEXT_IMG -> setQMUICommonItemViewHead(qMUICommonItemView, item)
+ }
+ }
+
+ /**
+ * 设置QMUICommonItemView 自定义布局
+ */
+ private fun setQMUICommonItemViewHead(
+ qMUICommonItemView: QMUICommonListItemView, item: MenuTxtBean
+ ) {
+ qMUICommonItemView.detailText = ""
+ qMUICommonItemView.accessoryType = QMUICommonListItemView.ACCESSORY_TYPE_CUSTOM
+ val view =
+ LayoutInflater.from(context).inflate(R.layout.layout_dfu_custom_qmui_group_right, null)
+ qMUICommonItemView.addAccessoryCustomView(view)
+
+ view.findViewById(R.id.iv_dfu_red_dot).visibility =
+ if (item.isSwitch) View.VISIBLE else View.GONE
+ val firmwareName = view.findViewById(R.id.tv_custom_group_dfu_detail_text)
+ firmwareName.text = item.menuValue
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HomePetTrackStateAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HomePetTrackStateAdapter.kt
new file mode 100644
index 0000000..880a721
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/HomePetTrackStateAdapter.kt
@@ -0,0 +1,60 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.constant.MultipleEntity
+import com.abbidot.tracker.widget.BatteryView
+import com.abbidot.tracker.widget.MyBluetoothAnimView
+import com.abbidot.tracker.widget.TypefaceTextView
+
+/**
+ * 首页宠物设备状态
+ */
+class HomePetTrackStateAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_home_pet_device_state
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: MenuTxtBean) {
+ val stateTextView = holder!!.getView(R.id.tv_home_pet_device_state_item) as TypefaceTextView
+ stateTextView.text = item.menuName
+
+ holder.getTextView(R.id.tv_home_pet_device_state_name_item).apply {
+ text = item.menuValue
+ setTextColor(ContextCompat.getColor(mContext, item.colorRedId))
+ }
+
+ val bv = holder.getView(R.id.bv_home_pet_device_power) as BatteryView
+ val bluetoothAnimView =
+ holder.getView(R.id.mba_home_pet_device_search_anim_item) as MyBluetoothAnimView
+ when (item.menuType) {
+ MultipleEntity.IMG_TEXT_IMG -> {
+ bluetoothAnimView.visibility = View.GONE
+ bv.visibility = View.VISIBLE
+ bv.setValue(item.imageId)
+ bluetoothAnimView.setBluetoothAnimStartAndStop(item.isSwitch)
+ stateTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
+ }
+
+ MultipleEntity.TEXT_TEXT_IMG -> {
+ bluetoothAnimView.visibility = View.VISIBLE
+ bv.visibility = View.GONE
+ bluetoothAnimView.setBluetoothAnimStartAndStop(item.isSwitch)
+ stateTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
+ }
+
+ else -> {
+ bv.visibility = View.GONE
+ bluetoothAnimView.visibility = View.GONE
+ stateTextView.setCompoundDrawablesWithIntrinsicBounds(0, item.imageId, 0, 0)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/HowWorkAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/HowWorkAdapter.kt
new file mode 100644
index 0000000..0c07328
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/HowWorkAdapter.kt
@@ -0,0 +1,27 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.qmuiteam.qmui.widget.grouplist.QMUICommonListItemView
+
+/**
+ *Created by .yzq on 2022/3/22/022.
+ * @link
+ * @description:
+ */
+class HowWorkAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_qmui_common_item_view
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: MenuTxtBean) {
+ val qMUICommonListItemView =
+ holder!!.getView(R.id.tracker_manage_setting_item) as QMUICommonListItemView
+ qMUICommonListItemView.detailText = item.menuValue
+ qMUICommonListItemView.text = item.menuName
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/LedLightColorAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/LedLightColorAdapter.kt
new file mode 100644
index 0000000..d47f3eb
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/LedLightColorAdapter.kt
@@ -0,0 +1,25 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.qmuiteam.qmui.widget.QMUIRadiusImageView
+
+/**
+ *Created by .yzq on 2021/12/30/030.
+ * @link
+ * @description:LedLight默认可以选择颜色适配器
+ */
+class LedLightColorAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_led_color_select
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: Int) {
+ val radiusImageView =
+ holder!!.itemView.findViewById(R.id.show_current_color_select)
+ radiusImageView.setImageResource(item)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/MySubscriptionAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/MySubscriptionAdapter.kt
new file mode 100644
index 0000000..0ecf5fd
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/MySubscriptionAdapter.kt
@@ -0,0 +1,193 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.content.Intent
+import android.view.LayoutInflater
+import android.view.View
+import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.baselibrary.util.MMKVUtil
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.SubscriptionsOrderBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.ui.activity.subscribe.ChoosePlanActivity
+import com.abbidot.tracker.ui.activity.subscribe.MySubscriptionActivity
+import com.abbidot.tracker.ui.activity.subscribe.SubscriptionHistoryActivity
+import com.abbidot.tracker.ui.activity.subscribe.SubscriptionPlanActivity
+import com.abbidot.tracker.widget.TypefaceTextView
+import com.qmuiteam.qmui.skin.QMUISkinManager
+import com.qmuiteam.qmui.widget.popup.QMUIPopup
+import com.qmuiteam.qmui.widget.popup.QMUIPopups
+
+
+/**
+ *Created by .yzq on 2024/3/29/029.
+ * @link
+ * @description:
+ */
+class MySubscriptionAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val mMySubscriptionActivity = ctx as MySubscriptionActivity
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_my_subscription_layout
+
+ override fun bindData(
+ holder: RecyclerViewHolder?, position: Int, item: SubscriptionsOrderBean
+ ) {
+ holder!!.setText(R.id.tv_my_subscription_device_out_id, item.deviceOutId)
+ holder.setText(R.id.tv_my_subscription_plan_name, "${item.mealName}(${item.planCategory})")
+ holder.getTextView(R.id.tv_my_subscription_auto_subscription_tips).apply {
+ visibility = if (item.subscriptionStatus == ConstantInt.Open) {
+ text = if (item.mealUnit == ConstantString.PackageUnitYear) String.format(
+ mContext.getString(R.string.txt_auto_subscription_year),
+ item.autoRenewPrice.toString()
+ )
+ else String.format(
+ mContext.getString(R.string.txt_auto_subscription_month),
+ item.autoRenewPrice.toString()
+ )
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+ }
+ holder.setText(
+ R.id.tv_my_subscription_active_time,
+ Utils.stringToDate(item.updateTime, resultFormat = Utils.DATE_FORMAT_PATTERN_EN6)
+ )
+
+ holder.getTextView(R.id.tv_my_subscription_annual_care).apply {
+ text =
+ if (item.annualCareType == ConstantInt.Type1) mContext.getString(R.string.start_txt_yes)
+ else mContext.getString(R.string.txt_no)
+ }
+
+// val timestamp = getAfterHowTimestamp(
+// Utils.stringToTimestamp(item.currentTime), item.surplusDays
+// )
+ holder.setText(
+ R.id.tv_my_subscription_expires_on,
+ Utils.formatTime(item.endTime, Utils.DATE_FORMAT_PATTERN_EN7)
+ )
+
+ if (item.subscriptionStatus == ConstantInt.Close) {
+ holder.setText(
+ R.id.tv_my_subscription_auto_renew,
+ mContext.getString(R.string.tracker_manage_set_led_off)
+ )
+ } else {
+ holder.setText(
+ R.id.tv_my_subscription_auto_renew,
+ mContext.getString(R.string.tracker_manage_set_led_on)
+ )
+ }
+
+ val expiresTitle = holder.getTextView(R.id.tv_my_subscription_expires_title)
+ holder.getButton(R.id.btn_my_subscription_recharge).apply {
+ visibility =
+ if (item.orderStatus == 6 || (item.surplusDays == 0L && item.subscriptionStatus == ConstantInt.Close)) {
+ setText(R.string.txt_card_recharge)
+ expiresTitle.setText(R.string.txt_expires_on2)
+ View.VISIBLE
+ } else if (item.subscriptionStatus == ConstantInt.Close) {
+ setText(R.string.txt_enable_auto_renew)
+ expiresTitle.setText(R.string.txt_expires_on1)
+ View.VISIBLE
+ } else {
+ expiresTitle.setText(R.string.txt_expires_on1)
+ View.GONE
+ }
+ }
+
+ holder.getView(R.id.il_my_subscription_count_down).apply {
+ visibility =
+ if (item.orderStatus == 6 || (item.surplusDays == 0L && item.subscriptionStatus == ConstantInt.Close)) {
+ View.GONE
+ } else {
+ View.VISIBLE
+ }
+ }
+
+ val times = Utils.getDayToYearMonthDay(item.surplusDays)
+ holder.setText(R.id.tv_add_success_device_expires_days, times[0])
+ holder.setText(R.id.tv_add_success_device_expires_hours, times[1])
+ holder.setText(R.id.tv_add_success_device_expires_min, times[2])
+
+ holder.getView(R.id.fl_my_subscription_btn_layout).apply {
+ val userId = MMKVUtil.getString(MMKVKey.UserId)
+ //UserId不一样就是共享设备的订单
+ visibility = if (item.userId == userId) {
+ setOnClickListener {
+ showPop(holder.getView(R.id.iv_my_subscription_btn), item, position)
+ }
+ View.VISIBLE
+ } else View.GONE
+ }
+ holder.setClickListener(R.id.btn_my_subscription_recharge) {
+ if (item.surplusDays == 0L && item.subscriptionStatus == ConstantInt.Close) {
+ Intent(mContext, SubscriptionPlanActivity::class.java).let {
+ it.putExtra(ConstantString.LkSetMeal, item)
+ mMySubscriptionActivity.startActivity(it)
+ }
+ } else {
+ mMySubscriptionActivity.updateSubscriptionStatus(item.subscriptionId, 1, position)
+ }
+ }
+ }
+
+ private fun showPop(v: View, item: SubscriptionsOrderBean, position: Int) {
+ val view = LayoutInflater.from(mContext).inflate(R.layout.pop_subscription_item, null)
+ val qMUIPopups =
+ QMUIPopups.popup(mContext).preferredDirection(QMUIPopup.DIRECTION_BOTTOM).view(view)
+// .edgeProtection(QMUIDisplayHelper.dp2px(mContext, 20))
+ .dimAmount(0.6f).arrowSize(AppUtils.dpToPx(6), AppUtils.dpToPx(4))
+ .radius(AppUtils.dpToPx(16)).animStyle(QMUIPopup.ANIM_GROW_FROM_CENTER)
+ .skinManager(QMUISkinManager.defaultInstance(mContext)).show(v)
+
+ view.findViewById(R.id.tv_pop_my_subscription_history).apply {
+ setOnClickListener {
+ qMUIPopups.dismiss()
+ Intent(mContext, SubscriptionHistoryActivity::class.java).let {
+ it.putExtra(ConstantString.DeviceId, item.deviceId)
+ mMySubscriptionActivity.startActivity(it)
+ }
+ }
+ }
+ //升级套餐
+ view.findViewById(R.id.tv_pop_my_subscription_auto_renew).apply {
+ visibility =
+ if (item.planCategory == "Premium" || (item.surplusDays == 0L && item.subscriptionStatus == ConstantInt.Close)) {
+ View.GONE
+ } else {
+ View.VISIBLE
+ }
+ setOnClickListener {
+ qMUIPopups.dismiss()
+ val intent = Intent(mContext, ChoosePlanActivity::class.java)
+ intent.putExtra(ConstantString.Title, "Premium")
+ intent.putExtra(ConstantString.Upgrade, true)
+ intent.putExtra(ConstantString.LkSetMeal, item)
+ mMySubscriptionActivity.startActivity(intent)
+ }
+ }
+ view.findViewById(R.id.tv_pop_my_subscription_cancel).apply {
+ visibility = if (item.subscriptionStatus == ConstantInt.Open) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+ setOnClickListener {
+ qMUIPopups.dismiss()
+ mMySubscriptionActivity.updateSubscriptionStatus(item.subscriptionId, 0, position)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/MyTrackerV2Adapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/MyTrackerV2Adapter.kt
new file mode 100644
index 0000000..a225529
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/MyTrackerV2Adapter.kt
@@ -0,0 +1,116 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.content.Intent
+import android.text.TextUtils
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DeviceBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.ui.activity.device.AddNewTracker1Activity
+import com.abbidot.tracker.ui.activity.device.MyTrackerV2Activity
+import com.abbidot.tracker.ui.activity.pet.PetProfileActivity
+import com.abbidot.tracker.util.ViewUtil
+import com.qmuiteam.qmui.widget.QMUIRadiusImageView
+
+/**
+ *Created by .yzq on 2024/3/7/007.
+ * @link
+ * @description:
+ */
+class MyTrackerV2Adapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val mMyTrackerActivity = mContext as MyTrackerV2Activity
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_my_tracker_v2_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DeviceBean) {
+ val batteryTextView = holder!!.getTextView(R.id.iv_item_my_tracker_v2_battery)
+ val trackerImageView = holder.getImageView(R.id.iv_item_my_tracker_v2_device)
+ val addTrackerLayout = holder.getView(R.id.ll_my_tracker_v2_add_tracker_layout)
+ val petHead = holder.getView(R.id.il_my_tracker_v2_pet_head) as QMUIRadiusImageView
+ val addPetLayout = holder.getView(R.id.ll_my_tracker_v2_add_pet_layout)
+ val trackerName = holder.getTextView(R.id.tv_my_tracker_v2_device_name)
+ val petName = holder.getTextView(R.id.tv_my_tracker_v2_pet_name)
+
+ holder.getImageView(R.id.iv_my_tracker_v2_share).apply {
+ visibility = if (item.shared == ConstantInt.NoShare) View.GONE else View.VISIBLE
+ }
+
+ addTrackerLayout.setOnClickListener {
+ if (itemCount - 1 == position) {
+ mMyTrackerActivity.startActivity(
+ Intent(
+ mContext, AddNewTracker1Activity::class.java
+ )
+ )
+ } else {
+ mMyTrackerActivity.getAssignData(position)
+ }
+ }
+ addPetLayout.setOnClickListener {
+ if (itemCount - 1 == position) {
+ mMyTrackerActivity.startActivity(Intent(mContext, PetProfileActivity::class.java))
+ } else {
+ mMyTrackerActivity.getAssignData(position)
+ }
+ }
+
+ trackerImageView.setOnClickListener {
+ if (item.shared == ConstantInt.NoShare) {
+ mMyTrackerActivity.showDeviceBottomSheetMenu(position)
+ }
+ }
+ petHead.setOnClickListener {
+ if (item.shared == ConstantInt.NoShare) {
+ mMyTrackerActivity.showPetBottomSheetMenu(position)
+ }
+ }
+
+ if (itemCount - 1 == position) {
+ batteryTextView.visibility = View.GONE
+ trackerImageView.visibility = View.GONE
+ trackerName.visibility = View.GONE
+ addTrackerLayout.visibility = View.VISIBLE
+
+ addPetLayout.visibility = View.VISIBLE
+ petHead.visibility = View.GONE
+ petName.visibility = View.GONE
+ } else {
+ if (TextUtils.isEmpty(item.deviceOutId)) {
+ addTrackerLayout.visibility = View.VISIBLE
+ batteryTextView.visibility = View.GONE
+ trackerImageView.visibility = View.GONE
+ trackerName.visibility = View.GONE
+ } else {
+ addTrackerLayout.visibility = View.GONE
+ batteryTextView.visibility = View.VISIBLE
+ trackerImageView.visibility = View.VISIBLE
+ trackerName.visibility = View.VISIBLE
+
+ trackerName.text = item.deviceOutId
+ val battery = "${item.batteryCapacity} "
+ batteryTextView.text = battery
+ }
+ if (null == item.pet) {
+ addPetLayout.visibility = View.VISIBLE
+ petHead.visibility = View.GONE
+ petName.visibility = View.GONE
+ } else {
+ addPetLayout.visibility = View.GONE
+ petHead.visibility = View.VISIBLE
+ petName.visibility = View.VISIBLE
+ item.pet?.let {
+ petName.text = it.petName
+ ViewUtil.instance.setPetTypeHead(petHead, it.imgurl, it.petType)
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/NotificationV2Adapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/NotificationV2Adapter.kt
new file mode 100644
index 0000000..49af39b
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/NotificationV2Adapter.kt
@@ -0,0 +1,73 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.text.TextUtils
+import android.text.format.DateUtils
+import android.view.View
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MessageBean
+import com.abbidot.tracker.widget.TypefaceRoundButton
+
+/**
+ *Created by .yzq on 2023/12/26/026.
+ * @link
+ * @description:
+ */
+class NotificationV2Adapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_home_route_notification
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: MessageBean) {
+ val roundButton =
+ holder!!.getView(R.id.iv_home_route_notification_state) as TypefaceRoundButton
+ val textColor = if (item.isRead) {
+ roundButton.visibility = View.GONE
+ R.color.black70
+ } else {
+ roundButton.visibility = View.VISIBLE
+ R.color.data_black_color
+ }
+ holder.getTextView(R.id.tv_home_route_notification_content).apply {
+ text = item.message
+ if (item.isSelect) {
+ ellipsize = null
+ isSingleLine = false
+ } else {
+ ellipsize = TextUtils.TruncateAt.END
+ isSingleLine = true
+ }
+ setTextColor(ContextCompat.getColor(mContext, textColor))
+ }
+ holder.getTextView(R.id.tv_home_route_notification_type).apply {
+ text = item.title
+ setTextColor(ContextCompat.getColor(mContext, textColor))
+ }
+ holder.getTextView(R.id.tv_home_route_notification_date).apply {
+ text = getRelativeTimeString(Utils.stringToTimestamp(item.sendTime))
+ setTextColor(ContextCompat.getColor(mContext, textColor))
+ }
+ }
+
+ private fun getRelativeTimeString(time: Long): String {
+ var formatDateStr = ""
+ val now = System.currentTimeMillis()
+ formatDateStr = if (DateUtils.isToday(time)) {
+ mContext.getString(R.string.txt_today) + " " + Utils.formatTime(
+ time, Utils.DATE_FORMAT_PATTERN_EN8
+ )
+ } else if (now - time < (48 * 60 * 60 * 1000)) {
+ mContext.getString(R.string.txt_yesterday)
+ } else {
+ Utils.formatTime(time, Utils.DATE_FORMAT_PATTERN_EN9)
+ }
+ return formatDateStr
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/PermissionsSetAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/PermissionsSetAdapter.kt
new file mode 100644
index 0000000..3cc98ac
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/PermissionsSetAdapter.kt
@@ -0,0 +1,66 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.ui.activity.set.PermissionsSetActivity
+import com.abbidot.tracker.widget.TypefaceButton
+
+/**
+ *Created by .yzq on 2024/3/25/025.
+ * @link
+ * @description:
+ */
+class PermissionsSetAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val mPermissionsSetActivity = ctx as PermissionsSetActivity
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_permission_state_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val stateView = holder!!.getImageView(R.id.cb_permission_state_item)
+ val typefaceTextView = holder.getTextView(R.id.tv_permission_tip_item)
+ val btnLayout = holder.getView(R.id.ll_permission_set_layout)
+ val btnSkip = holder.getView(R.id.btn_permission_skip_set) as TypefaceButton
+ val btnEnable = holder.getView(R.id.btn_permission_enable_set) as TypefaceButton
+ btnSkip.visibility = View.INVISIBLE
+ btnEnable.setChangeAlphaWhenPress(true)
+ btnEnable.setText(R.string.txt_turn_on_upper)
+
+ if (item.selected) {
+ typefaceTextView.visibility = View.VISIBLE
+ btnLayout.visibility = View.VISIBLE
+ holder.itemView.setBackgroundResource(R.drawable.shape16_white_color_bg)
+ } else {
+ btnLayout.visibility = View.GONE
+ typefaceTextView.visibility = View.GONE
+ holder.itemView.setBackgroundResource(R.drawable.shape10_white_bg)
+ }
+
+ when (item.state) {
+ ConstantInt.Type0 -> stateView.setImageResource(R.drawable.icon_permission_error_check_svg)
+ ConstantInt.Type1 -> stateView.setImageResource(R.drawable.icon_permission_check_svg)
+ }
+
+ holder.setText(R.id.tv_permission_name_item, item.name)
+ typefaceTextView.text = item.value
+
+ btnEnable.setOnClickListener {
+ when (position) {
+ 0 -> mPermissionsSetActivity.mPermissionsCommon.operateBluetooth()
+ 1 -> mPermissionsSetActivity.mPermissionsCommon.operateGPSLocation()
+ 2 -> mPermissionsSetActivity.mPermissionsCommon.operateNotifications(
+ this, ConstantInt.Type0
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/PetLabelsAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/PetLabelsAdapter.kt
new file mode 100644
index 0000000..17650ba
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/PetLabelsAdapter.kt
@@ -0,0 +1,57 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.LabelBean
+import com.qmuiteam.qmui.layout.QMUILinearLayout
+import kotlin.random.Random
+
+/**
+ *Created by .yzq on 2024/2/21/021.
+ * @link
+ * @description:
+ */
+class PetLabelsAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+
+ private val mLabelBgColorList = mutableListOf(
+ R.color.green_color10,
+ R.color.label_color2,
+ R.color.label_color3,
+ R.color.label_color4,
+ R.color.label_color5,
+ R.color.label_color6,
+ R.color.label_color7,
+ R.color.label_color8,
+ R.color.label_color9,
+ R.color.label_color10,
+ R.color.label_color11,
+ R.color.label_color12,
+ R.color.label_color13,
+ R.color.label_color14
+ )
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_pet_label_layout_v2
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: LabelBean) {
+ val textView = holder!!.getTextView(R.id.tv_label_v2_name)
+ val rootView = holder.itemView as QMUILinearLayout
+ val imageView = holder.getImageView(R.id.iv_label_v2_is_select)
+ if (item.check) {
+ imageView.visibility = View.VISIBLE
+ } else {
+ imageView.visibility = View.GONE
+ }
+ textView.text = item.name
+
+ rootView.setBackgroundResource(mLabelBgColorList[Random.nextInt(mLabelBgColorList.size)])
+
+ rootView.radius = AppUtils.dpToPx(6)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/PetsBadgesAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/PetsBadgesAdapter.kt
new file mode 100644
index 0000000..b9f0c4f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/PetsBadgesAdapter.kt
@@ -0,0 +1,31 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+
+/**
+ *Created by .yzq on 2021/12/30/030.
+ * @link
+ * @description:
+ */
+class PetsBadgesAdapter(ctx: Context, list: MutableList?,itemViewWidthDp:Int=80) :
+ BaseRecyclerAdapter(ctx, list) {
+
+ private val mItemViewWidthDp=AppUtils.dpToPx(itemViewWidthDp)
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_pets_badges_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ holder!!.getTextView(R.id.tv_item_my_pets_badge).apply {
+ text = item.name
+ }
+ holder.itemView.layoutParams.width= mItemViewWidthDp
+ holder.getImageView(R.id.iv_item_my_pets_badge).setImageResource(item.imageId)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/PetsParentBadgesAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/PetsParentBadgesAdapter.kt
new file mode 100644
index 0000000..7e15840
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/PetsParentBadgesAdapter.kt
@@ -0,0 +1,89 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.content.Intent
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.ParentBadgeBean
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.ui.activity.pet.BadgeDetailActivity
+import com.abbidot.tracker.util.ViewUtil
+import com.abbidot.tracker.widget.TypefaceButton
+
+/**
+ *Created by .yzq on 2021/12/30/030.
+ * @link
+ * @description:
+ */
+class PetsParentBadgesAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+
+ //默认显示的勋章个数
+ private val defaultShowCount = 9
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_pets_parent_badges_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: ParentBadgeBean) {
+ val recyclerView = holder!!.getView(R.id.rv_pet_badges_list) as RecyclerView
+ holder.setText(R.id.tv_pets_parent_badges_name, item.parentName)
+ val btn = (holder.getView(R.id.btn_parent_badges_expand_fold) as TypefaceButton).apply {
+ visibility = View.GONE
+ if (item.isExpand) {
+ setText(R.string.txt_view_less)
+ } else {
+ setText(R.string.txt_see_all)
+ }
+ setOnClickListener {
+ item.isExpand = !item.isExpand
+ notifyItemChanged(position)
+ }
+ }
+ item.badgeList?.apply {
+ if (size > defaultShowCount) {
+ btn.visibility = View.VISIBLE
+ } else {
+ btn.visibility = View.GONE
+ }
+ }
+
+ val list = if (item.isExpand || null == item.badgeList || item.badgeList!!.size < 4) {
+ item.badgeList
+ } else {
+ item.badgeList!!.subList(0, defaultShowCount)
+ }
+ if (null == recyclerView.adapter) {
+ val petsBadgesAdapter = PetsBadgesAdapter(mContext, list).apply {
+ setOnItemClickListener(object : OnItemClickListener {
+ override fun onItemClick(itemView: View?, pos: Int) {
+ val activity = mContext as BaseActivity<*>
+ Intent(mContext, BadgeDetailActivity::class.java).let {
+ it.putExtra(ConstantString.PetLabels, list!![pos])
+ activity.startActivity(it)
+ }
+ }
+ })
+ }
+
+ ViewUtil.instance.setRecyclerViewGridLayout(
+ mContext,
+ recyclerView,
+ petsBadgesAdapter,
+ 3,
+ AppUtils.dpToPx(80),
+ top = AppUtils.dpToPx(16),
+ bottom = AppUtils.dpToPx(18),
+ offset = AppUtils.dpToPx(32)
+ )
+ } else {
+ val adapter = recyclerView.adapter as PetsBadgesAdapter
+ adapter.setData(list, true)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/SelectFencesTypeCardShadeAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/SelectFencesTypeCardShadeAdapter.kt
new file mode 100644
index 0000000..a28254a
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/SelectFencesTypeCardShadeAdapter.kt
@@ -0,0 +1,37 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.cardview.widget.CardView
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.qmuiteam.qmui.util.QMUIDisplayHelper
+
+/**
+ */
+class SelectFencesTypeCardShadeAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_select_type_card_shade_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val imageView = holder!!.getImageView(R.id.iv_select_type_image)
+ imageView.setImageResource(item.imageId)
+ val cardView = holder.itemView as CardView
+ cardView.apply {
+ isSelected = item.selected
+ cardElevation = if (item.selected) {
+ setCardBackgroundColor(ContextCompat.getColor(context, R.color.select_color))
+ QMUIDisplayHelper.dpToPx(4).toFloat()
+ } else {
+ setCardBackgroundColor(ContextCompat.getColor(context, R.color.transparent))
+ 0f
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/SelectMapListDialogAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/SelectMapListDialogAdapter.kt
new file mode 100644
index 0000000..52dc62b
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/SelectMapListDialogAdapter.kt
@@ -0,0 +1,29 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MenuTxtBean
+
+/**
+ *Created by .yzq on 2022/1/10/010.
+ * @link
+ * @description:选择地图应用列表弹窗
+ */
+class SelectMapListDialogAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_select_map
+
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: MenuTxtBean) {
+ val textView = holder!!.getTextView(R.id.item_select_map_name)
+ textView.text = item.menuName
+ textView.setCompoundDrawablesWithIntrinsicBounds(
+ item.imageId, 0, 0, 0)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/SelectMapTypeCardShadeAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/SelectMapTypeCardShadeAdapter.kt
new file mode 100644
index 0000000..ee6aed2
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/SelectMapTypeCardShadeAdapter.kt
@@ -0,0 +1,41 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.cardview.widget.CardView
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+
+/**
+ */
+class SelectMapTypeCardShadeAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_map_type_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val imageView = holder!!.getImageView(R.id.iv_select_type_image)
+ imageView.setImageResource(item.imageId)
+ holder.setText(R.id.tv_map_type_name, item.name)
+ val cardView = holder.getView(R.id.il_map_type_shade_image) as CardView
+ cardView.apply {
+ isSelected = item.selected
+ cardElevation = if (item.selected) {
+ setCardBackgroundColor(ContextCompat.getColor(context, R.color.white))
+ val padding = AppUtils.dpToPx(3)
+ setContentPadding(padding, padding, padding, padding)
+ AppUtils.dpToPx(4).toFloat()
+ } else {
+ setCardBackgroundColor(ContextCompat.getColor(context, R.color.transparent))
+ setContentPadding(0, 0, 0, 0)
+ 0f
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/SpaceItemDecoration.kt b/app/src/main/java/com/abbidot/tracker/adapter/SpaceItemDecoration.kt
new file mode 100644
index 0000000..86b23a6
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/SpaceItemDecoration.kt
@@ -0,0 +1,37 @@
+package com.abbidot.tracker.adapter
+
+import android.graphics.Rect
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+
+/**
+ *Created by .yzq on 2021/12/24/024.
+ * @link https://qa.1r1g.com/sf/ask/1997239751/
+ * @description:RecyclerView的LinearLayoutManager和FlexboxLayoutManager通用item间距设置
+ */
+class SpaceItemDecoration(
+ left: Int = 0, right: Int = 0, top: Int = 0, bottom: Int = 0
+) : RecyclerView.ItemDecoration() {
+
+ private var mLeft = left
+ private var mRight = right
+ private var mTop = top
+ private var mBottom = bottom
+
+ override fun getItemOffsets(
+ outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
+ ) {
+ if (mLeft > 0) {
+ outRect.left = mLeft
+ }
+ if (mRight > 0) {
+ outRect.right = mRight
+ }
+ if (mTop > 0) {
+ outRect.top = mTop
+ }
+ if (mBottom > 0) {
+ outRect.bottom = mBottom
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionHistoryAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionHistoryAdapter.kt
new file mode 100644
index 0000000..a283407
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionHistoryAdapter.kt
@@ -0,0 +1,122 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.content.Intent
+import android.view.View
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.SubscriptionsOrderBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.ui.activity.subscribe.RequestRefundActivity
+import com.abbidot.tracker.ui.activity.subscribe.SubscriptionHistoryActivity
+import com.abbidot.tracker.widget.TypefaceRoundButton
+
+/**
+ *Created by .yzq on 2024/8/19/019.
+ * @link
+ * @description:
+ */
+class SubscriptionHistoryAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val mHistoryActivity = ctx as SubscriptionHistoryActivity
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_subscription_history_layout
+
+ override fun bindData(
+ holder: RecyclerViewHolder?, position: Int, item: SubscriptionsOrderBean
+ ) {
+ holder!!.setText(
+ R.id.tv_subscription_history_order_id,
+ mContext.getString(R.string.txt_order_id) + item.orderNum
+ )
+ holder.setText(
+ R.id.tv_subscription_history_order_time,
+ Utils.stringToDate(item.createTime, resultFormat = Utils.DATE_FORMAT_PATTERN_EN10)
+ )
+ holder.setText(R.id.tv_subscription_history_package_name, item.mealName)
+ holder.setText(
+ R.id.tv_subscription_history_package_price,
+ String.format(mContext.getString(R.string.txt_money_unit), "${item.totalAmountWithTax}")
+ )
+
+
+ (holder.getView(R.id.btn_subscription_history_operate) as TypefaceRoundButton).apply {
+
+ setTextColor(ContextCompat.getColor(mContext, R.color.line_color1))
+
+ if (item.enabled == ConstantInt.Type0) visibility = View.GONE
+ else {
+ visibility = View.VISIBLE
+ when (item.orderStatus) {
+ 1 -> {
+ val updateTimestamp = Utils.stringToTimestamp(item.updateTime)
+ val nowTimestamp = System.currentTimeMillis()
+// val nowTimestamp = Utils.stringToTimestamp(item.currentTime)
+ if (item.mealUnit == ConstantString.PackageUnitMonth) {
+ val day7Timestamp = 7 * 24 * 60 * 60 * 1000L
+ //套餐超出7天不能退款
+ if (nowTimestamp - updateTimestamp <= day7Timestamp) {
+ visibility = View.VISIBLE
+ setText(R.string.txt_refund)
+ } else {
+ visibility = View.GONE
+ }
+ } else {
+ val day30Timestamp = 30 * 24 * 60 * 60 * 1000L
+ //套餐超出30天不能退款
+ if (nowTimestamp - updateTimestamp <= day30Timestamp) {
+ visibility = View.VISIBLE
+ setText(R.string.txt_refund)
+ } else {
+ visibility = View.GONE
+ }
+ }
+ setTextColor(ContextCompat.getColor(mContext, R.color.select_color))
+ }
+
+ 4 -> setText(R.string.txt_waiting)
+ 5 -> setText(R.string.txt_refunding)
+ 6 -> setText(R.string.txt_refunded)
+ 7, 8 -> {
+ setTextColor(ContextCompat.getColor(mContext, R.color.orange_red_color))
+ setText(R.string.txt_rejected)
+ }
+
+ else -> visibility = View.GONE
+ }
+ }
+
+ setChangeAlphaWhenPress(true)
+ setOnClickListener {
+ if (item.orderStatus == ConstantInt.Type1) {
+ Intent(mContext, RequestRefundActivity::class.java).apply {
+ putExtra(ConstantString.SetMeal, item)
+ mHistoryActivity.startActivity(this)
+ }
+ }
+ }
+ }
+
+ val state =
+ if (item.enabled == ConstantInt.Type0 || (item.surplusDays == 0L && item.subscriptionStatus == ConstantInt.Close)) {
+ mContext.getString(R.string.txt_expired)
+ } else {
+ mContext.getString(R.string.txt_active)
+ }
+ holder.setText(R.id.tv_subscription_history_subscription_state, state)
+
+ holder.getTextView(R.id.tv_subscription_history_annual_care).apply {
+ text =
+ if (item.annualCareType == ConstantInt.Type1) mContext.getString(R.string.start_txt_yes)
+ else mContext.getString(R.string.txt_no)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionPlanAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionPlanAdapter.kt
new file mode 100644
index 0000000..ae672e4
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionPlanAdapter.kt
@@ -0,0 +1,45 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.widget.RelativeLayout
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.PackageTypeBean
+
+/**
+ *Created by .yzq on 2024/3/19/019.
+ * @link
+ * @description:
+ */
+class SubscriptionPlanAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_subscription_plan_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: PackageTypeBean) {
+ val relativeLayout = holder!!.getView(R.id.rl_subscribe_plan_shade_item) as RelativeLayout
+// val popularCardView = holder.getView(R.id.cv_subscribe_plan_item_popular) as CardView
+// val subscription = holder.getTextView(R.id.tv_subscribe_plan_item_per_year)
+
+ if (item.selected) {
+ relativeLayout.setBackgroundResource(R.drawable.shape20_yellow_border_cyan_bg)
+// popularCardView.visibility = View.VISIBLE
+ } else {
+ relativeLayout.setBackgroundResource(0)
+// popularCardView.visibility = View.GONE
+ }
+ holder.setText(R.id.tv_subscribe_plan_item_name, item.name)
+ holder.setText(
+ R.id.tv_subscribe_plan_item_money,
+ String.format(mContext.getString(R.string.txt_money_unit), Utils.formatDecimal( item.price, 2))
+ )
+// subscription.text =
+// String.format(mContext.getString(R.string.txt_per_year_money), item.subscriptionFee)
+// subscription.visibility = if (item.subscriptionFee == 0.0) View.INVISIBLE
+// else View.VISIBLE
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionPlanDetailAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionPlanDetailAdapter.kt
new file mode 100644
index 0000000..0369e71
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/SubscriptionPlanDetailAdapter.kt
@@ -0,0 +1,31 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.appcompat.widget.AppCompatCheckBox
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.PackageBenefitsBean
+import com.abbidot.tracker.constant.ConstantInt
+
+/**
+ *Created by .yzq on 2024/3/19/019.
+ * @link
+ * @description:
+ */
+class SubscriptionPlanDetailAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_subscription_plan_detail_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: PackageBenefitsBean) {
+ val checkBox = holder!!.getView(R.id.cb_subscribe_plan_detail_item) as AppCompatCheckBox
+ checkBox.setOnClickListener {
+ checkBox.isChecked = !checkBox.isChecked
+ }
+ holder.setText(R.id.tv_subscribe_plan_detail_name, item.title)
+ checkBox.isChecked = item.status == ConstantInt.Open
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/SureSubscribeSummaryAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/SureSubscribeSummaryAdapter.kt
new file mode 100644
index 0000000..7d07159
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/SureSubscribeSummaryAdapter.kt
@@ -0,0 +1,34 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MenuTxtBean
+
+/**
+ *Created by .yzq on 2024/9/9/009.
+ * @link
+ * @description:
+ */
+class SureSubscribeSummaryAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_subscribe_summary_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: MenuTxtBean) {
+ holder?.apply {
+ setText(R.id.tv_subscribe_summary_item_name, item.menuName)
+ getTextView(R.id.tv_subscribe_summary_item_money).let {
+ val string =
+ String.format(mContext.getString(R.string.txt_money_unit), item.menuValue)
+ it.text = if (item.isSwitch) "-$string"
+ else string
+ it.setTextColor(ContextCompat.getColor(mContext, item.colorRedId))
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/TextViewAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/TextViewAdapter.kt
new file mode 100644
index 0000000..8d3158b
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/TextViewAdapter.kt
@@ -0,0 +1,25 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+
+/**
+ *Created by .yzq on 2024/2/20/020.
+ * @link
+ * @description:
+ */
+class TextViewAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_text_view
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ holder!!.setText(R.id.tv_text_view_item, item.name)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/ViewPagerAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/ViewPagerAdapter.kt
new file mode 100644
index 0000000..18b04cf
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/ViewPagerAdapter.kt
@@ -0,0 +1,21 @@
+package com.abbidot.tracker.adapter
+
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+/**
+ *Created by .yzq on 2021/11/19/019.
+ * @link
+ * @description:
+ */
+class ViewPagerAdapter(list: MutableList, fragmentActivity: FragmentActivity) :
+ FragmentStateAdapter(fragmentActivity) {
+
+ private val mFragmentList = list
+
+ override fun getItemCount() = mFragmentList.size
+
+ override fun createFragment(position: Int) = mFragmentList[position]
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/VirtualFencesZoneShadeAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/VirtualFencesZoneShadeAdapter.kt
new file mode 100644
index 0000000..564e274
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/VirtualFencesZoneShadeAdapter.kt
@@ -0,0 +1,34 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import androidx.cardview.widget.CardView
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.DataBean
+import com.qmuiteam.qmui.util.QMUIDisplayHelper
+
+/**
+ *围栏类型
+ */
+class VirtualFencesZoneShadeAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_shadow_image_view
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DataBean) {
+ val imageView = holder!!.getImageView(R.id.iv_item_shadow_image_view)
+ val cardView = holder.itemView as CardView
+
+ if (item.selected) {
+ imageView.setImageResource(item.selectImageId)
+ cardView.cardElevation = QMUIDisplayHelper.dpToPx(4).toFloat()
+ } else {
+ imageView.setImageResource(item.imageId)
+ cardView.cardElevation = 0f
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/WiFiListAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/WiFiListAdapter.kt
new file mode 100644
index 0000000..93a3e17
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/WiFiListAdapter.kt
@@ -0,0 +1,39 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.WiFiBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.widget.MyWiFiSignalView
+
+/**
+ *Created by .yzq on 2024/3/26/026.
+ * @link
+ * @description:
+ */
+class WiFiListAdapter(
+ ctx: Context, list: MutableList?
+) : BaseRecyclerAdapter(ctx, list) {
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_wifi_info_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: WiFiBean) {
+// val wifiName = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+// item.wifiSsid.toString()
+// } else {
+// item.SSID
+// }
+ holder!!.setText(R.id.tv_wifi_item_name, item.name)
+ val signalView = holder.getView(R.id.tv_wifi_item_signal) as MyWiFiSignalView
+ val signal = Utils.calculateSignalLevel(item.signal, 3)
+ if (item.auth_type == ConstantInt.Type0) {
+ signalView.setValue(signal)
+ } else {
+ signalView.setValue(signal, true)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/adapter/WiFiZoneAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/WiFiZoneAdapter.kt
new file mode 100644
index 0000000..260056d
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/adapter/WiFiZoneAdapter.kt
@@ -0,0 +1,43 @@
+package com.abbidot.tracker.adapter
+
+import android.content.Context
+import android.view.View
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.WiFiZoneBean
+import com.abbidot.tracker.constant.ConstantInt
+
+/**
+ */
+class WiFiZoneAdapter(
+ ctx: Context, list: MutableList?, isShowArrowRight: Boolean = true
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val isShowArrow = isShowArrowRight
+
+ override fun getEmptyLayoutId(viewType: Int) = R.layout.layout_virtual_fences_empty_view
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_wifi_zone_layout
+
+ override fun noData(holder: RecyclerViewHolder?) {
+ holder?.apply {
+ getView(R.id.btn_empty_fences_add_safe_zone).visibility =
+ if (isShowNoDataAddButton) View.VISIBLE
+ else View.GONE
+ }
+ }
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: WiFiZoneBean) {
+ holder!!.setText(R.id.tv_wifi_zone_name, item.wifiZoneName)
+ holder.setText(R.id.tv_wifi_zone_address, item.address)
+ val wifiZoneTypeImage =
+ if (item.type == ConstantInt.Type1) R.drawable.icon_wifi_zone_type1_svg
+ else R.drawable.icon_wifi_zone_type2_svg
+ holder.getImageView(R.id.iv_wifi_zone_type).setBackgroundResource(wifiZoneTypeImage)
+
+ holder.getImageView(R.id.iv_wifi_zone_list_arrow_right).visibility =
+ if (isShowArrow) View.VISIBLE
+ else View.GONE
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/alipay/PayResult.kt b/app/src/main/java/com/abbidot/tracker/alipay/PayResult.kt
new file mode 100644
index 0000000..001d31b
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/alipay/PayResult.kt
@@ -0,0 +1 @@
+package com.abbidot.tracker.alipay
import android.text.TextUtils
/**
* 支付宝支付验证消息
*/
class PayResult(rawResult: Map?) {
/**
* @return the resultStatus
*/
var resultStatus: String? = null
/**
* @return the result
*/
var result: String? = null
/**
* @return the memo
*/
var memo: String? = null
override fun toString(): String {
return "resultStatus={$resultStatus};memo={$memo};result={$result}"
}
init {
rawResult?.let {
for (key in it.keys) {
when {
TextUtils.equals(key, "resultStatus") -> {
resultStatus = it[key]
}
TextUtils.equals(key, "result") -> {
result = it[key]
}
TextUtils.equals(key, "memo") -> {
memo = it[key]
}
}
}
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt b/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt
new file mode 100644
index 0000000..70d199f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt
@@ -0,0 +1,799 @@
+package com.abbidot.tracker.base
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.graphics.Rect
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.view.Window
+import android.view.inputmethod.InputMethodManager
+import android.widget.Button
+import android.widget.EditText
+import androidx.activity.OnBackPressedCallback
+import androidx.activity.result.ActivityResultLauncher
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentTransaction
+import androidx.viewbinding.ViewBinding
+import com.abbidot.baselibrary.network.exception.ErrorCode
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.baselibrary.util.LogUtil
+import com.abbidot.tracker.R
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.util.ViewUtil
+import com.hjq.toast.Toaster
+import com.qmuiteam.qmui.alpha.QMUIAlphaButton
+import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton
+import com.qmuiteam.qmui.util.QMUIDisplayHelper
+import com.qmuiteam.qmui.util.QMUIStatusBarHelper
+import com.qmuiteam.qmui.widget.QMUITopBar
+import com.qmuiteam.qmui.widget.dialog.QMUITipDialog
+
+
+/**
+ *Created by .yzq on 2021/11/2/002.
+ * @link
+ * @description: Activity基类
+ */
+abstract class BaseActivity(val inflater: (inflater: LayoutInflater) -> T) :
+ AppCompatActivity(), View.OnClickListener {
+
+ protected lateinit var mViewBinding: T
+ var mTopBar: QMUITopBar? = null
+ lateinit var mContext: Context
+ lateinit var mActivity: Activity
+ private var mLoadingDialog: QMUITipDialog? = null
+
+ //默认删除去掉titleTopBar底部间隔下划线
+ var mDeleteBottomDivider: Boolean = true
+
+ //Activity是否在前台显示运行
+ var isFrontRunning = false
+
+ //是否需要通知上个页面更新数据
+ var isNotifyUpdate = false
+
+ //右边图标按钮
+ var mRightImageButton: QMUIAlphaImageButton? = null
+
+ //右边按钮
+ var mRightTextButton: Button? = null
+
+ //网络请求失败,需要重试次数
+ var mNetworkRequestsFailRetryCount = 0
+ val mNetworkRequestsFailMaxCount = 3
+ val mNetworkRequestsFailLimit = "networkRequestsFailLimit"
+
+ //是否拦截网络请求错误code提示
+ var isInterceptNetErrorCodeTip = false
+
+ //软键盘管理
+ private var mInputMethodManager: InputMethodManager? = null
+
+ // 监听因输入框弹出,遮挡输入框,界面移动,需要移动的view
+ private var mTranslateView: View? = null
+
+ /*****************************监听软键盘弹出,输入框上移start************************************/
+ private var isKeyboardTranslate = true
+
+ //是否需要适配底部EdgeToEdge
+ var isEdgeToEdgeAdapterNavigationBars = true
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ isFrontRunning = true
+ super.onCreate(savedInstanceState)
+ mViewBinding = inflater(layoutInflater)
+ mContext = this
+ mActivity = this
+ //禁用屏幕旋转 代码设置无效
+// requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ mViewBinding.root.apply {
+ //点击屏幕页面隐藏软键盘start
+ setOnClickListener {
+ hideInputMethod(this)
+ }
+
+ //判断是否是深色模式
+ if (AppUtils.isDarkThemeEnabled(mContext)) {
+ // 设备处于深色模式
+ setBackgroundResource(R.color.gray)
+ } else {
+ // 设备处于浅色模式,统一设置的渐变背景色
+ background = ContextCompat.getDrawable(mContext, R.drawable.v2_bg_color_gradient)
+ }
+ }
+ setContentView(mViewBinding.root)
+ mTopBar = getTopBar()
+
+ //拦截返回按键
+ onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ listenBackPressed()
+ //Removing this callback
+// remove()
+// onBackPressedDispatcher.onBackPressed()
+ }
+ })
+
+ initData()
+ liveDataObserve()
+ }
+
+ // 字体大小不跟随系统
+ override fun attachBaseContext(newBase: Context) {
+ super.attachBaseContext(getConfigurationContext(newBase))
+ }
+
+ // 字体大小不跟随系统
+ private fun getConfigurationContext(context: Context): Context {
+ val configuration = context.resources.configuration
+ configuration.fontScale = 1F
+ return context.createConfigurationContext(configuration)
+ }
+
+ /*
+ lifecycleScope.launch {
+
+ Dispatchers.IO
+ 专为磁盘和网络IO进行了优化
+ 数据库-文件读写-网络处理
+ Dispatchers.Default
+ 专为CPU密集型任务进行了优化
+ 数组排序 - JSON数据解析-处理差异判断
+ withContext(Dispatchers.Default){
+
+ }
+ lifecycleScope.coroutineContext
+ }
+ */
+
+ override fun onResume() {
+ super.onResume()
+ isFrontRunning = true
+ }
+
+ override fun onPause() {
+ super.onPause()
+ //键盘隐藏恢复默认状态
+ mTranslateView?.apply {
+ scrollTo(0, 0)
+ isKeyboardTranslate = false
+ }
+ }
+
+ override fun onStop() {
+ super.onStop()
+ showLoading(false)
+ isFrontRunning = false
+ }
+
+ /**
+ * 没有TopBar就设置返回null
+ */
+ abstract fun getTopBar(): QMUITopBar?
+
+ /**
+ * 注册监听livedata观察者
+ */
+ open fun liveDataObserve() {}
+
+ /**
+ * open修饰的类和方法可以被子类继承和重写
+ * 初始化
+ */
+ open fun initData() {
+ //沉浸式状态栏
+ QMUIStatusBarHelper.translucent(window)
+ //判断是否是深色模式
+ if (AppUtils.isDarkThemeEnabled(mContext)) {
+ setStatusBarDark()
+ } else {
+ setStatusBarLight()
+ }
+ mTopBar?.apply {
+ //适配状态栏
+ this.parent?.let {
+ edgeToEdgeAdapterBars(it as View, WindowInsetsCompat.Type.statusBars())
+ }
+ //去掉titleTopBar底部间隔下划线
+ if (mDeleteBottomDivider) updateBottomDivider(0, 0, 0, 0)
+ }
+ //适配底部导航栏
+ if (isEdgeToEdgeAdapterNavigationBars) edgeToEdgeAdapterBars(mViewBinding.root)
+ }
+
+ /**
+ * 和 setContentView 对应的方法
+ */
+ private fun getContentView(): ViewGroup {
+ return findViewById(Window.ID_ANDROID_CONTENT)
+ }
+
+ /**
+ * 监听键盘弹出和隐藏,解决键盘弹出隐藏输入框的问题
+ */
+ fun setListenKeyboardChange(windowTranslateY: Int = 500, view: View = window.decorView) {
+ window.decorView.viewTreeObserver.addOnGlobalLayoutListener {
+ onLayoutChange(view, windowTranslateY)
+ }
+ }
+
+ /**
+ * 设置其他包含的view点击。隐藏软键盘,如ScrollView
+ */
+ fun setViewClickHideInputMethod(view: View) {
+ // 点击外部隐藏软键盘,提升用户体验
+ view.setOnClickListener {
+ hideInputMethod(view)
+ }
+ }
+
+ /**
+ * edgeToEdge全面屏适配Android15 底部。防止view被菜单、状态栏遮挡
+ * https://mp.weixin.qq.com/s?__biz=MzA5MzI3NjE2MA==&mid=2650286452&idx=1&sn=354b78ae82c52b6d3d510256779a3df9&scene=21&poc_token=HN91iGij_n_mGA9z9ZarQC_44XYBhBjN9N9z_w1_
+ */
+ fun edgeToEdgeAdapterBars(
+ view: View, typeMask: Int = WindowInsetsCompat.Type.navigationBars()
+ ) {
+ ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
+ val bars = insets.getInsets(typeMask)
+ v.setPadding(bars.left, bars.top, bars.right, bars.bottom)
+ insets
+ }
+ }
+
+ /**
+ * 修改状态颜色,有状态栏时用到,现在状态栏直接被占位
+ */
+// fun setStatusBarColor(color: Int) {
+// //这里动态修改颜色
+// window.statusBarColor = color
+// }
+
+ /**
+ * 设置状态栏白色字体与图标
+ */
+ fun setStatusBarDark() {
+ QMUIStatusBarHelper.setStatusBarDarkMode(this)
+ }
+
+ /**
+ * 设置状态栏黑色字体与图标
+ */
+ fun setStatusBarLight() {
+ QMUIStatusBarHelper.setStatusBarLightMode(this)
+ }
+
+ /**
+ * 设置多个view的监听事件
+ */
+ fun setOnClickListenerViews(vararg views: View?) {
+ for (v in views) {
+ v?.let {
+ if (v is QMUIAlphaButton) {
+ //设置按下点击透明效果
+ v.setChangeAlphaWhenPress(true)
+ } else if (v is QMUIAlphaImageButton) {
+ //设置按下点击透明效果
+ v.setChangeAlphaWhenPress(true)
+ }
+ v.setOnClickListener(this)
+ }
+ }
+ }
+
+ override fun onClick(v: View?) {
+ // 默认不实现,让子类实现
+ }
+
+ /**
+ * 按钮开启/禁用点击
+ */
+ fun setButtonEnabled(v: View, enabled: Int = ConstantInt.SpecialType) {
+ when (enabled) {
+ ConstantInt.SpecialType -> v.isEnabled = !v.isEnabled
+ ConstantInt.Type0 -> v.isEnabled = false
+ ConstantInt.Type1 -> v.isEnabled = true
+ }
+ }
+
+ /**
+ * 设置title标题 resIdTitle
+ */
+ fun setTopBarTitle(resIdTitle: Int) {
+ setTopBarTitle(getString(resIdTitle))
+ }
+
+ /**
+ * 设置透明一体化状态栏TopBarTitle,只有返回按钮
+ */
+ fun setTranslucentTopBar() {
+ //去掉titleTopBar背景颜色,设置TopBar背景透明
+ mTopBar!!.setBackgroundAlpha(0)
+ setTopBarTitle("")
+ }
+
+ /**
+ * 设置按钮图片
+ */
+ fun setLeftBackImage(@DrawableRes resId: Int) {
+ mTopBar!!.removeAllLeftViews()
+ val leftBtn = mTopBar!!.addLeftImageButton(resId, R.id.topbar_left_change_button)
+ if (resId == 0) {
+ return
+ }
+ leftBtn.setOnClickListener { leftBackOnClick() }
+ }
+
+ /**
+ * 需要重写返回按钮时
+ */
+ open fun leftBackOnClick() {
+ finish()
+ }
+
+ /**
+ * 拦截返回按键
+ */
+// override fun onBackPressed() {
+// leftBackOnClick()
+// super.onBackPressed()
+// }
+
+ open fun listenBackPressed() {
+ leftBackOnClick()
+ }
+
+
+ /**
+ * 添加TopBar右边图片按钮
+ */
+ fun addRightImageButton(@DrawableRes resId: Int): QMUIAlphaImageButton {
+ val rightBtn = mTopBar!!.addRightImageButton(resId, R.id.topbar_right_change_button)
+ setOnClickListenerViews(rightBtn)
+ return rightBtn
+ }
+
+ /**
+ * 添加TopBar右边文字按钮
+ */
+ fun addRightTextButton(
+ @StringRes resId: Int, textColor: Int = R.color.select_color
+ ): Button {
+ val textButton = mTopBar!!.addRightTextButton(
+ getString(resId), R.id.topbar_right_change_textview
+ ).apply {
+ setBackgroundResource(R.drawable.selector_transparent_pressed)
+ setTextColor(ContextCompat.getColor(mContext, textColor))
+ setOnClickListenerViews(this)
+ }
+ return textButton
+ }
+
+ /**
+ * 设置title标题titleString
+ */
+ fun setTopBarTitle(title: String) {
+ if (null != mTopBar) {
+ if (TextUtils.isEmpty(title)) mTopBar!!.showTitleView(false)
+ else {
+ mTopBar!!.setTitle(title)
+ val tf =
+ ViewUtil.instance.setTypeface(mContext, getString(R.string.roboto_bold_font))
+ mTopBar!!.titleView!!.setTypeface(tf)
+ }
+ mTopBar!!.addLeftBackImageButton().setOnClickListener { leftBackOnClick() }
+ }
+ }
+
+ fun isShowLoading(): Boolean {
+ if (null != mLoadingDialog && mLoadingDialog!!.isShowing) {
+ return true
+ }
+ return false
+ }
+
+ fun showLoading(show: Boolean, tipsRes: Int, cancelable: Boolean = true) {
+ showLoading(show, getString(tipsRes), cancelable)
+ }
+
+ fun showLoading(show: Boolean, tip: String = "", cancelable: Boolean = true) {
+// if (!isFrontRunning) {
+// return
+// }
+// if (show) {
+// if (isShowLoading()) {
+// mLoadingDialog!!.dismiss()
+// }
+// var message = tip
+// if (TextUtils.isEmpty(tip)) {
+// message = getString(R.string.txt_loading)
+// }
+// mLoadingDialog =
+// QMUITipDialog.Builder(mContext).setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
+// .setTipWord(message).create(cancelable).apply {
+// setCanceledOnTouchOutside(false)
+// show()
+// }
+// } else {
+// mLoadingDialog?.dismiss()
+// }
+ }
+
+ fun showNoCancelableLoading(show: Boolean) {
+ if (!isFrontRunning) {
+ return
+ }
+ if (show) {
+ if (isShowLoading()) {
+ mLoadingDialog!!.dismiss()
+ }
+// var message = tip
+// if (TextUtils.isEmpty(tip)) {
+// }
+ val message = getString(R.string.txt_loading)
+ mLoadingDialog =
+ QMUITipDialog.Builder(mContext).setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
+ .setTipWord(message).create(false).apply {
+ setCanceledOnTouchOutside(false)
+ show()
+ }
+ } else {
+ mLoadingDialog?.dismiss()
+ }
+ }
+
+ /**
+ * 显示提示toast
+ */
+ fun showToast(
+ tip: String, isFinish: Boolean = false, gravity: Int = Gravity.BOTTOM
+// @QMUITipDialog.Builder.IconType iconType: Int = QMUITipDialog.Builder.ICON_TYPE_NOTHING
+ ) {
+ if (gravity == Gravity.BOTTOM) Toaster.setGravity(gravity, 0, 300, 0f, 0f)
+ if (isFinish) {
+// DialogUtils.showTipDialog(mContext, mViewBinding.root, tip, iconType, true)
+ //activity前台显示运行才弹出
+ if (isFrontRunning) {
+ Toaster.show(tip)
+ //根据文字长度来决定显示时间长短
+ var showTime = if (AppUtils.isChina()) {
+ tip.length * (1000L / 4)
+ } else {
+ tip.length * (1000L / 10)
+ }
+ if (showTime < 1000) showTime = 1500
+ if (showTime > 8000) showTime = 8000
+ mViewBinding.root.postDelayed({
+ if (!isFinishing) {
+ Toaster.cancel()
+ finish()
+ }
+ }, showTime)
+ }
+ } else {
+ Toaster.show(tip)
+ }
+ }
+
+ fun showToast(
+ resIdString: Int, isFinish: Boolean = false, gravity: Int = Gravity.BOTTOM
+// @QMUITipDialog.Builder.IconType iconType: Int = QMUITipDialog.Builder.ICON_TYPE_NOTHING
+ ) {
+ showToast(getString(resIdString), isFinish, gravity)
+ }
+
+ fun hideFragment(fragmentTransaction: FragmentTransaction, fragment: Fragment) {
+ if (fragment.isAdded) {
+ fragmentTransaction.hide(fragment)
+ }
+ }
+
+ override fun finish() {
+ super.finish()
+ overridePendingTransition(R.anim.slide_still, R.anim.slide_out_right)
+ }
+
+ override fun startActivity(intent: Intent) {
+ super.startActivity(intent)
+ overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
+ }
+
+ fun startActivityFinish(intent: Intent) {
+ startActivity(intent)
+ super.finish()
+ }
+
+ override fun startActivity(intent: Intent, options: Bundle?) {
+ super.startActivity(intent, options)
+ overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
+ }
+
+ /**
+ * onActivityResult 替换跳转方法
+ */
+ fun launchActivity(activityResultLauncher: ActivityResultLauncher, intent: Intent) {
+ activityResultLauncher.launch(intent)
+ overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)
+ }
+
+ /**
+ * 统一处理网络请求结果
+ */
+ fun dealRequestResult(
+ it: Result,
+ getResultCallback: GetResultCallback,
+ showLoading: Boolean = false,
+ isShowNoDataTip: Boolean = true,
+ isShowRequestErrorTip: Boolean = true,
+ errorTip: String = getString(R.string.txt_net_error)
+ ) {
+ try {
+ showLoading(showLoading)
+ //服务器返回错误信息
+ val exceptionMessage = it.exceptionOrNull()?.message
+ //服务器返回错误code
+ val exceptionCode: String? = it.exceptionOrNull()?.toString()
+ LogUtil.d("Throwable?", "code=${exceptionCode},${exceptionMessage}")
+ if (null != exceptionCode) {
+ //处理注册用户已存在的情况
+ if (exceptionCode == ErrorCode.USER_HAS_EXIST.toString()) {
+ getResultCallback.onRequestError(exceptionCode)
+ }
+ //拦截请求异常code
+ if (netErrorCodeTips(exceptionCode)) {
+ //已经处理相关错误码就直接返回
+ return
+ }
+ }
+
+ val data = it.getOrNull()
+ if (null == data) {
+ if (isShowRequestErrorTip) showToast(errorTip)
+ if (mNetworkRequestsFailRetryCount < mNetworkRequestsFailMaxCount) {
+ mNetworkRequestsFailRetryCount++
+ getResultCallback.onRequestError(exceptionCode)
+ } else {
+ //请求次数上限
+ getResultCallback.onRequestError(mNetworkRequestsFailLimit)
+ }
+ } else {
+ mNetworkRequestsFailRetryCount = 0
+ if (isShowNoDataTip && data is MutableList<*> && data.size == 0) {
+ showToast(R.string.no_data)
+ }
+ //不做强制类型转换
+ getResultCallback.onResult(0)
+ }
+ } catch (e: Exception) {
+ LogUtil.e("接口出错造成的异常:${e.message}")
+ }
+ }
+
+ /**
+ * 网络请求错误code提示
+ */
+ private fun netErrorCodeTips(exceptionCode: String): Boolean {
+ //设备已过期,请续费
+ when (exceptionCode) {
+ ErrorCode.DEVICE_RENEWAL.toString() -> {
+ showToast(R.string.txt_device_renewal)
+ return true
+ }
+ //TOKEN失效或者过期
+ ErrorCode.TOKEN_OVERDUE.toString() -> {
+ showToast(R.string.txt_token_overdue)
+ return true
+ }
+ //用户名或密码错误
+ ErrorCode.USER_PASSWORD_ERROR.toString() -> {
+ showToast(R.string.txt_user_password_error, gravity = Gravity.CENTER)
+ return true
+ }
+ //验证码错误
+ ErrorCode.VERIFY_CODE_ERROR.toString() -> {
+ showToast(R.string.txt_verify_code_error, gravity = Gravity.CENTER)
+ return true
+ }
+ //验证码已过期
+ ErrorCode.VERIFY_CODE_EXPIRE.toString() -> {
+ showToast(R.string.txt_verify_code_expire, gravity = Gravity.CENTER)
+ return true
+ }
+ //注册失败
+ ErrorCode.REGISTER_FAIL.toString() -> {
+ showToast(R.string.txt_register_fail, gravity = Gravity.CENTER)
+ return true
+ }
+ //用户不存在
+ ErrorCode.USER_NO_EXIST.toString() -> {
+ showToast(R.string.txt_user_no_exist, gravity = Gravity.CENTER)
+ return true
+ }
+ //用户已存在
+ ErrorCode.USER_HAS_EXIST.toString() -> {
+ if (!isInterceptNetErrorCodeTip) {
+ showToast(R.string.txt_user_has_exist, gravity = Gravity.BOTTOM)
+ }
+ return true
+ }
+ //邮箱格式不对
+ ErrorCode.EMAIL_FORMAT_ERROR.toString() -> {
+ showToast(R.string.txt_email_format_error, gravity = Gravity.CENTER)
+ return true
+ }
+ //不能分享给自己
+ ErrorCode.NO_SHARE_MYSELF.toString() -> {
+ showToast(R.string.txt_no_share_myself)
+ return true
+ }
+ //当前用户已经绑定该设备
+ ErrorCode.DEVICE_HAS_BOUND.toString() -> {
+ showToast(R.string.txt_device_has_bound)
+ return true
+ }
+ //该设备已被绑定
+ ErrorCode.DEVICE_HAS_BIND.toString() -> {
+ showToast(R.string.txt_device_has_bind)
+ return true
+ }
+ //设备不存在
+ ErrorCode.DEVICE_NOT_EXIST.toString() -> {
+ showToast(R.string.txt_no_dfu)
+ return true
+ }
+
+ else -> return false
+ }
+ }
+
+ /**
+ * 监听软键盘隐藏
+ */
+ open fun listenHideKeyboard() {}
+
+ /******************************点击屏幕页面隐藏软键盘start**************************************/
+// override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
+// if (ev.action == MotionEvent.ACTION_DOWN) {
+// val v = currentFocus
+// v?.let {
+// //如果搜索框内没有输入,隐藏键盘时则返回Contacts页面
+// if (isShouldHideKeyboard(v, ev)) {
+// if (hideInputMethod(it)) {
+// LogUtil.e("dispatchTouchEvent-->listenHideKeyboard,隐藏键盘")
+// listenHideKeyboard()
+// //这里可以执行隐藏需要执行的任务;
+// //隐藏键盘时,其他控件不响应点击事件==》注释则不拦截点击事件
+// //不拦截事件,按钮需要事件
+//// return true
+// }
+// }
+// }
+//
+// }
+// return super.dispatchTouchEvent(ev)
+// }
+
+ /**
+ * 获取InputMethodManager
+ */
+ private fun getInputMethodManager(): InputMethodManager? {
+ if (null == mInputMethodManager) mInputMethodManager =
+ getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ return mInputMethodManager
+ }
+
+ /**
+ * 隐藏软键盘
+ */
+ fun hideInputMethod(view: View): Boolean {
+ getInputMethodManager()?.apply {
+ return hideSoftInputFromWindow(view.windowToken, 0)
+ }
+ return false
+ }
+
+ /**
+ * 弹出软键盘
+ */
+ fun showInputMethod(view: View) {
+ getInputMethodManager()?.apply {
+ showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
+ }
+ }
+
+ /**
+ * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时则不能隐藏
+ */
+ private fun isShouldHideKeyboard(v: View?, ev: MotionEvent): Boolean {
+ if (v != null && (v is EditText)) {
+ val l = intArrayOf(0, 0)
+ v.getLocationInWindow(l)
+ val left = l[0]
+ val top = l[1]
+ val bottom = top + v.getHeight()
+ val right = left + v.getWidth()
+ return !(ev.x > left && ev.x < right && ev.y > top && ev.y < bottom)
+ }
+ // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
+ return false
+ }
+
+ /******************************点击屏幕页面隐藏软键盘end**************************************/
+
+
+ /**
+ * 软键盘显示
+ */
+ open fun showSoftKeyboardCallback() {
+ LogUtil.e("监听重写软键盘弹出")
+ }
+
+ /**
+ * 软键盘隐藏
+ */
+ open fun hideSoftKeyboardCallback() {
+ LogUtil.e("监听重写软键盘隐藏")
+ }
+
+ /*
+ * 获取导航栏高度
+ */
+ private fun getNavigatorBarHeight(): Int {
+// val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
+// val height = resources.getDimensionPixelSize(resourceId)
+ return QMUIDisplayHelper.getNavMenuHeight(mContext)
+ }
+
+ /**
+ * 监听因输入框弹出,遮挡输入框,界面移动
+ * @param translateView 需要移动的view
+ * @param translateY 移动的坐标点
+ */
+ private fun onLayoutChange(translateView: View, translateY: Int) {
+ mTranslateView = translateView
+ //获取当前屏幕内容的高度
+ val screenHeight = window.decorView.height
+ //获取View可见区域的bottom
+ val rect = Rect()
+ window.decorView.getWindowVisibleDisplayFrame(rect)
+ if (screenHeight - getNavigatorBarHeight() > rect.bottom) {
+ // 获取按钮的左上角,按钮高度为40dp
+// val location = IntArray(2)
+// translateView.getLocationOnScreen(location)
+// val bottom = location[1] + resources.getDimensionPixelSize(R.dimen.dp_80)
+//// 如果按钮被覆盖,移动整个界面向上移动
+// if (bottom > rect.bottom) {
+// window.decorView.scrollBy(0, bottom - rect.bottom)
+// isKeyboardTranslate = true
+// }
+ if (!isKeyboardTranslate) {
+ //移动到指定位置点坐标
+ translateView.scrollBy(0, translateY)
+ isKeyboardTranslate = true
+ }
+ LogUtil.e("软键盘弹出")
+ showSoftKeyboardCallback()
+ } else {
+ LogUtil.e("隐藏软键盘")
+ if (isKeyboardTranslate) {
+ translateView.scrollTo(0, 0)
+ isKeyboardTranslate = false
+ }
+ hideSoftKeyboardCallback()
+ }
+ }
+ /*****************************监听软键盘弹出,输入框上移end************************************/
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseDialog.kt b/app/src/main/java/com/abbidot/tracker/base/BaseDialog.kt
new file mode 100644
index 0000000..0394f07
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseDialog.kt
@@ -0,0 +1,96 @@
+package com.abbidot.tracker.base
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.OnClickListener
+import android.view.WindowManager
+import androidx.annotation.StyleRes
+import androidx.appcompat.app.AppCompatDialog
+import androidx.viewbinding.ViewBinding
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.qmuiteam.qmui.alpha.QMUIAlphaButton
+import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton
+
+
+/**
+ *Created by .yzq on 2022/1/11/011.-
+ * @link
+ * @dialogHeightDp 默认高度350dp
+ * @description:BaseDialog
+ */
+abstract class BaseDialog
+ (
+ val inflater: (inflater: LayoutInflater) -> T,
+ context: Context,
+ dialogHeightDp: Int = 0,
+ @StyleRes animationResId: Int = R.style.QMUI_Animation_Scale,
+ @StyleRes themeResId: Int = R.style.my_Dialog_shadow_style
+) : AppCompatDialog(context, themeResId), OnClickListener {
+
+ protected lateinit var mViewBinding: T
+
+ val mContext = context
+
+ private val mAnimationResId = animationResId
+ private val mDialogHeightDp = dialogHeightDp
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ mViewBinding = inflater(layoutInflater)
+ setContentView(mViewBinding.root)
+ //设置Dialog动画
+ window!!.setWindowAnimations(mAnimationResId)
+ //设置弹窗的高度
+ val layoutParams: WindowManager.LayoutParams = window!!.attributes
+ if (mDialogHeightDp == 0) {
+ //采用自适应高度
+ layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
+ } else {
+ layoutParams.height = AppUtils.dpToPx(mDialogHeightDp)
+ }
+// layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT
+ window!!.attributes = layoutParams
+
+ initView()
+ }
+
+ abstract fun initView()
+
+ /**
+ * 设置多个view的监听事件
+ */
+ fun setOnClickListenerViews(vararg views: View?) {
+ for (v in views) {
+ v?.let {
+ if (v is QMUIAlphaButton) {
+ //设置按下点击透明效果
+ v.setChangeAlphaWhenPress(true)
+ } else if (v is QMUIAlphaImageButton) {
+ //设置按下点击透明效果
+ v.setChangeAlphaWhenPress(true)
+ }
+ v.setOnClickListener(this)
+ }
+ }
+ }
+
+ override fun onClick(v: View) {
+ // 默认不实现,让子类实现
+ }
+
+ interface OnDialogOkListener {
+ fun onOkClick(dialog: BaseDialog<*>)
+ }
+
+ interface OnDialogSelectListener {
+ fun onSelectClick(dialog: BaseDialog<*>, any: Any)
+ }
+
+ interface OnDialogCancelListener {
+ fun onCancelClick(dialog: BaseDialog<*>)
+ }
+}
+
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseDiffBean.kt b/app/src/main/java/com/abbidot/tracker/base/BaseDiffBean.kt
new file mode 100644
index 0000000..ae739eb
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseDiffBean.kt
@@ -0,0 +1,14 @@
+package com.abbidot.tracker.base
+
+/**
+ *Created by .yzq on 2022/4/20/020.
+ * @link
+ * @description:
+ */
+abstract class BaseDiffBean {
+ // 判断当前对象和给定对象是否是同一对象
+ abstract fun isSameObject(other: Any): Boolean
+
+ // 判断当前对象和给定对象是否拥有相同内容
+ abstract fun hasSameContent(other: Any): Boolean
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseDiffCallBack.kt b/app/src/main/java/com/abbidot/tracker/base/BaseDiffCallBack.kt
new file mode 100644
index 0000000..c5cfff1
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseDiffCallBack.kt
@@ -0,0 +1,57 @@
+package com.abbidot.tracker.base
+
+import androidx.recyclerview.widget.DiffUtil
+
+/**
+ *Created by .yzq on 2021/11/12/012.
+ * @link
+ * @description: DiffUtil基类封装
+ */
+open class BaseDiffCallBack(oldList: MutableList?, newList: MutableList?) :
+ DiffUtil.Callback() {
+
+ private var mOldList: MutableList? = oldList
+ private var mNewList: MutableList? = newList
+
+ override fun getOldListSize() = if (mOldList == null) {
+ 0
+ } else mOldList!!.size
+
+ override fun getNewListSize() = if (mNewList == null) {
+ 0
+ } else mNewList!!.size
+
+ /**
+ * 判断新旧item是否是同一个item,最好以唯一不变的id作比较
+ */
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+// if (null == mNewList || null == mOldList) return false
+ val newItem = mNewList!![newItemPosition]
+ if (newItem is BaseDiffBean) {
+ return newItem.isSameObject(mOldList!![oldItemPosition]!!)
+ }
+ return true
+ }
+
+ /**
+ * 是同一个item。然后比较新旧item的内容是否一样
+ */
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ val newItem = mNewList!![newItemPosition]
+ if (newItem is BaseDiffBean) {
+ return newItem.hasSameContent(mOldList!![oldItemPosition]!!)
+ }
+ return false
+ }
+
+ /**
+ * 局部刷新比较,只更新某个item
+ */
+ override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
+ val newDeviceBean = mNewList?.get(newItemPosition)
+ if (!areContentsTheSame(oldItemPosition, newItemPosition)) {
+ return newDeviceBean
+ }
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseFragment.kt b/app/src/main/java/com/abbidot/tracker/base/BaseFragment.kt
new file mode 100644
index 0000000..5b0e8b8
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseFragment.kt
@@ -0,0 +1,167 @@
+package com.abbidot.tracker.base
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.activity.result.ActivityResultLauncher
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.viewbinding.ViewBinding
+import com.abbidot.baselibrary.util.LogUtil
+import com.abbidot.tracker.R
+import com.abbidot.tracker.constant.GetResultCallback
+import com.qmuiteam.qmui.alpha.QMUIAlphaButton
+import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton
+import com.qmuiteam.qmui.widget.dialog.QMUITipDialog
+
+/**
+ *Created by .yzq on 2021/11/2/002.
+ * @link
+ * @description:Fragment基类
+ * 关于@JvmOverloads constructor说明 https://stackoverflow.com/questions/34469487/caused-by-java-lang-nosuchmethodexception-init-class-android-content-contex
+ */
+abstract class BaseFragment(
+ val inflater: (inflater: LayoutInflater, container: ViewGroup?, attachToRoot: Boolean) -> T
+) : Fragment(), View.OnClickListener {
+
+ protected lateinit var mViewBinding: T
+ var mActivity: Activity? = null
+ var mContext: Context? = null
+ var mLoadingDialog: QMUITipDialog? = null
+
+ /**
+ * Fragment中嵌套子Fragment时,如果父Fragment被销毁而子Fragment未被销毁,会导致子Fragment的视图不再显示
+ */
+ override fun onCreate(savedInstanceState: Bundle?) {
+ savedInstanceState?.remove("android:support:fragments")
+ super.onCreate(savedInstanceState)
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View? {
+ mViewBinding = this.inflater(inflater, container, false)
+ LogUtil.e("${javaClass.simpleName},onCreateView")
+ return mViewBinding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ mActivity = activity
+ mContext = context
+ //统一设置的渐变背景色
+ mViewBinding.root.background =
+ ContextCompat.getDrawable(mContext!!, R.drawable.v2_bg_color_gradient)
+ LogUtil.e("${javaClass.simpleName},onViewCreated")
+ initData()
+ liveDataObserve()
+ }
+
+
+ /**
+ * 注册监听livedata观察者
+ */
+ open fun liveDataObserve() {}
+
+ /**
+ * 初始化
+ */
+ open fun initData() {}
+
+ fun showLoading(show: Boolean, tip: String = "", cancelable: Boolean = true) {
+ (activity as BaseActivity<*>).showLoading(show, tip, cancelable)
+ }
+
+ fun showLoading(show: Boolean) {
+ (activity as BaseActivity<*>).showLoading(show)
+ }
+
+ fun showNoCancelableLoading(show: Boolean) {
+ (activity as BaseActivity<*>).showNoCancelableLoading(show)
+ }
+
+ /**
+ * 显示提示toast
+ */
+ fun showToast(
+ tip: String, isFinish: Boolean = false, gravity: Int = Gravity.BOTTOM
+ ) {
+// DialogUtils.showTipDialog(mContext!!, mViewBinding.root, tip, iconType, isFinish = isFinish)
+ (activity as BaseActivity<*>).showToast(tip, isFinish, gravity)
+ }
+
+ fun showToast(
+ resIdString: Int, isFinish: Boolean = false, gravity: Int = Gravity.BOTTOM
+ ) {
+// showToast(getString(resIdString), isFinish, iconType)
+ (activity as BaseActivity<*>).showToast(resIdString, isFinish, gravity)
+ }
+
+ /**
+ * 设置多个view的监听事件
+ */
+ fun setOnClickListenerViews(vararg views: View?) {
+ for (v in views) {
+ v?.let {
+ if (v is QMUIAlphaButton) {
+ //设置按下点击透明效果
+ v.setChangeAlphaWhenPress(true)
+ } else if (v is QMUIAlphaImageButton) {
+ //设置按下点击透明效果
+ v.setChangeAlphaWhenPress(true)
+ }
+ v.setOnClickListener(this)
+ }
+ }
+ }
+
+ override fun onClick(v: View?) {
+ // 默认不实现,让子类实现
+ }
+
+ fun finish(activity: Activity) {
+ (activity as BaseActivity<*>).finish()
+ }
+
+ fun startActivity(activity: Activity, intent: Intent) {
+ (activity as BaseActivity<*>).startActivity(intent)
+ }
+
+ fun startActivityFinish(activity: Activity, intent: Intent) {
+ (activity as BaseActivity<*>).startActivityFinish(intent)
+ }
+
+ fun startActivity(activity: Activity, intent: Intent, options: Bundle?) {
+ (activity as BaseActivity<*>).startActivity(intent, options)
+ }
+
+ /**
+ * onActivityResult 替换跳转方法
+ */
+ fun launchActivity(
+ activity: Activity, activityResultLauncher: ActivityResultLauncher, intent: Intent
+ ) {
+ (activity as BaseActivity<*>).launchActivity(activityResultLauncher, intent)
+ }
+
+ /**
+ * 统一处理网络请求结果
+ */
+ fun dealRequestResult(
+ it: Result,
+ getResultCallback: GetResultCallback,
+ showLoading: Boolean = false,
+ isShowNoDataTip: Boolean = true,
+ isRequestErrorTip: Boolean = true,
+ errorTip: String = getString(R.string.txt_net_error)
+ ) {
+ (activity as BaseActivity<*>).dealRequestResult(
+ it, getResultCallback, showLoading, isShowNoDataTip, isRequestErrorTip, errorTip
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseMapCommon.kt b/app/src/main/java/com/abbidot/tracker/base/BaseMapCommon.kt
new file mode 100644
index 0000000..ed6b00f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseMapCommon.kt
@@ -0,0 +1,195 @@
+package com.abbidot.tracker.base
+
+import android.content.Context
+import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.util.MMKVUtil
+import com.abbidot.tracker.bean.FencesBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.ui.fragment.map.baidumap.BaseBaiduMapFragment
+import com.abbidot.tracker.ui.fragment.map.googlemap.BaseGoogleMapFragment
+import com.abbidot.tracker.util.Util
+import com.baidu.mapapi.utils.DistanceUtil
+import com.google.android.gms.maps.model.LatLng
+
+/**
+ *Created by .yzq on 2024/5/10/010.
+ * @link
+ * @description:重复调用方法写在这个类中
+ */
+open class BaseMapCommon {
+
+ /**
+ * 地图是否加载好了,准备好了
+ */
+ fun isMapLoadOk(
+ baiduMapFragment: BaseBaiduMapFragment?, googleMapFragment: BaseGoogleMapFragment?
+ ): Boolean {
+ var loadOK = false
+ if (null != baiduMapFragment) {
+ loadOK = baiduMapFragment.isMapLoadOk
+ } else if (null != googleMapFragment) {
+ loadOK = googleMapFragment.isMapLoadOk
+ }
+ return loadOK
+ }
+
+ /**
+ * 开始每隔几秒刷新用户位置
+ */
+ fun startRefreshUserLocation(
+ baiduMapFragment: BaseBaiduMapFragment?, googleMapFragment: BaseGoogleMapFragment?
+ ) {
+ googleMapFragment?.getLastLocation()
+ }
+
+ /**
+ * 切换地图类型
+ */
+ fun switchSatelliteAndNormalMapType(
+ baiduMapFragment: BaseBaiduMapFragment?, googleMapFragment: BaseGoogleMapFragment?
+ ) {
+ val mapTypeSp = Util.getMapTypeSp()
+ if (mapTypeSp == ConstantInt.Type0) {
+ MMKVUtil.putInt(MMKVKey.MapType, ConstantInt.Type1)
+ } else {
+ MMKVUtil.putInt(MMKVKey.MapType, ConstantInt.Type0)
+ }
+ if (null != baiduMapFragment) {
+ baiduMapFragment.switchSatelliteAndNormalMapType()
+ } else googleMapFragment?.switchSatelliteAndNormalMapType()
+ }
+
+ /**
+ * 设置宠物当前经纬度和头像
+ */
+ fun setPetHeadAndCurrentLocation(
+ petHeadUrl: String,
+ petType: Int,
+ lat: Double,
+ lon: Double,
+ baiduMapFragment: BaseBaiduMapFragment?,
+ googleMapFragment: BaseGoogleMapFragment?
+ ) {
+ if (null != googleMapFragment) {
+ googleMapFragment.setPetCurrentLocation(petHeadUrl, lat, lon, petType)
+ } else baiduMapFragment?.setPetCurrentLocation(petHeadUrl, lat, lon)
+ }
+
+ /**
+ * 切换用户和宠物的位置居中显示
+ */
+ fun switchShowLocationType(
+ @ConstantInt type: Int,
+ baiduMapFragment: BaseBaiduMapFragment?,
+ googleMapFragment: BaseGoogleMapFragment?
+ ) {
+ if (null != baiduMapFragment) {
+ baiduMapFragment.switchShowLocation(type)
+ } else googleMapFragment?.switchShowLocation(type)
+ }
+
+ /**
+ * 切换用户、宠物和第三方的位置(围栏或者wifi zone)居中显示
+ */
+ fun switchShowLocationType(
+ @ConstantInt type: Int,
+ lat: Double,
+ lon: Double,
+ baiduMapFragment: BaseBaiduMapFragment?,
+ googleMapFragment: BaseGoogleMapFragment?
+ ) {
+ if (null != baiduMapFragment) {
+ if (type == ConstantInt.OtherLocationType) {
+ baiduMapFragment.moveCameraLocation(lat, lon)
+ } else {
+ baiduMapFragment.switchShowLocation(type)
+ }
+ } else if (null != googleMapFragment) {
+ if (type == ConstantInt.OtherLocationType) {
+ googleMapFragment.moveCameraUpdate(lat, lon)
+ } else {
+ googleMapFragment.switchShowLocation(type)
+ }
+ }
+ }
+
+
+ /**
+ * 根据预览围栏类型设置地图等级
+ * @param padding 距离屏幕边缘的距离,px单位
+ */
+ fun restoreFencesSetMapZoom(
+ context: Context,
+ fencesBean: FencesBean,
+ baiduMapFragment: BaseBaiduMapFragment?,
+ googleMapFragment: BaseGoogleMapFragment?,
+ padding: Int
+ ) {
+ fencesBean.apply {
+ when (fenceShapeType) {
+ ConstantInt.CircleShapeType -> {
+ googleMapFragment?.apply {
+ setLatLngZoom(
+ context,
+ padding,
+ LatLng(ancillaryLatitude, ancillaryLongitude),
+ LatLng(ancillaryOtherLatitude, ancillaryOtherLongitude)
+ )
+ }
+ baiduMapFragment?.apply {
+ setBaiduMapZoom(getDistanceZoom(radius.toDouble()) + 1)
+ }
+ }
+
+ ConstantInt.RectangleShapeType -> {
+ googleMapFragment?.setLatLngZoom(
+ context,
+ padding,
+ LatLng(latitudeA, longitudeA),
+ LatLng(latitudeB, longitudeB),
+ LatLng(latitudeC, longitudeC),
+ LatLng(latitudeD, longitudeD)
+ )
+ baiduMapFragment?.apply {
+ setBaiduMapZoom(
+ getDistanceZoom(
+ maxOf(
+ shortDistance, longDistance
+ ).toDouble()
+ ) + 1
+ )
+ }
+ }
+
+ ConstantInt.PolygonShapeType -> {
+ googleMapFragment?.setLatLngZoom(
+ context,
+ padding,
+ LatLng(latitudeA, longitudeA),
+ LatLng(latitudeB, longitudeB),
+ LatLng(latitudeC, longitudeC),
+ LatLng(latitudeD, longitudeD),
+ LatLng(latitudeE, longitudeE),
+ LatLng(latitudeF, longitudeF),
+ )
+ baiduMapFragment?.apply {
+ val minLat =
+ minOf(latitudeA, latitudeB, latitudeC, latitudeD, latitudeE, latitudeF)
+ val maxLat =
+ minOf(latitudeA, latitudeB, latitudeC, latitudeD, latitudeE, latitudeF)
+ val minLon = minOf(
+ longitudeA, longitudeB, longitudeC, longitudeD, longitudeE, longitudeF
+ )
+ val maxLon = minOf(
+ longitudeA, longitudeB, longitudeC, longitudeD, longitudeE, longitudeF
+ )
+ val distance = DistanceUtil.getDistance(
+ getBaiduMapLatLng(minLat, minLon), getBaiduMapLatLng(maxLat, maxLon)
+ )
+ setBaiduMapZoom(getDistanceZoom(distance))
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseQMUIRVItemSwipeAction.kt b/app/src/main/java/com/abbidot/tracker/base/BaseQMUIRVItemSwipeAction.kt
new file mode 100644
index 0000000..694e39f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseQMUIRVItemSwipeAction.kt
@@ -0,0 +1,25 @@
+package com.abbidot.tracker.base
+
+import androidx.recyclerview.widget.RecyclerView
+import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction
+
+/**
+ *Created by .yzq on 2021/11/22/022.
+ * @link
+ * @description: QMUIRVItemSwipeAction.Callback
+ */
+abstract class BaseQMUIRVItemSwipeAction(swipeDirection: Int) : QMUIRVItemSwipeAction.Callback() {
+
+ private val mSwipeDirection = swipeDirection
+
+ abstract fun removeItem(position: Int)
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ removeItem(viewHolder.adapterPosition)
+ }
+
+ override fun getSwipeDirection(recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder): Int {
+ return mSwipeDirection
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseSwipeMenuAdapter.kt b/app/src/main/java/com/abbidot/tracker/base/BaseSwipeMenuAdapter.kt
new file mode 100644
index 0000000..ef6955f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseSwipeMenuAdapter.kt
@@ -0,0 +1,152 @@
+package com.abbidot.tracker.base
+
+import android.content.Context
+import android.graphics.Color
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.qmuiteam.qmui.recyclerView.QMUISwipeAction
+import com.qmuiteam.qmui.recyclerView.QMUISwipeAction.ActionBuilder
+import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder
+import com.qmuiteam.qmui.util.QMUIDisplayHelper
+
+
+/**
+ *Created by .yzq on 2021/11/20/020.
+ * @link
+ * @description:带有滑动删除菜单列表适配器,配合DiffUtil使用取消notifyDataSetChanged()方法
+ */
+abstract class BaseSwipeMenuAdapter(context: Context, list: MutableList) :
+ RecyclerView.Adapter() {
+
+ private var mData: MutableList = list
+ private val mContext: Context = context
+ private val mInflater: LayoutInflater = LayoutInflater.from(context)
+
+ private var mClickListener: BaseRecyclerAdapter.OnItemClickListener? = null
+ private var mLongClickListener: BaseRecyclerAdapter.OnItemLongClickListener? = null
+
+ // 是否显示空布局,默认显示
+ private var showEmptyView = true
+
+ //重试事件
+ private var mAgainClickListener: BaseRecyclerAdapter.OnAgainClickListener? = null
+
+ /**
+ * viewType--分别为item以及空view
+ */
+ private val mViewTypeEmpty = 0
+ private val mViewTypeItem = 1
+
+ //菜单样式Builder
+ var mActionBuilder: ActionBuilder =
+ ActionBuilder().textSize(QMUIDisplayHelper.sp2px(context, 14)).textColor(Color.WHITE)
+ .paddingStartEnd(QMUIDisplayHelper.dp2px(context, 14))
+
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QMUISwipeViewHolder {
+ //空布局
+ if (getEmptyLayoutId(viewType) != 0 && viewType == mViewTypeEmpty) {
+ val itemView: View = mInflater.inflate(getEmptyLayoutId(viewType), parent, false)
+ val swipeViewHolder = QMUISwipeViewHolder(itemView)
+ if (null != mAgainClickListener) {
+ itemView.setOnClickListener {
+ showEmptyView(false)
+ mAgainClickListener!!.onAgainListener()
+ }
+ }
+ return swipeViewHolder
+ } else {
+ val itemView: View = mInflater.inflate(getItemLayoutId(viewType), parent, false)
+ val swipeViewHolder = QMUISwipeViewHolder(itemView)
+ //添加滑动菜单
+ for (swipeAction in getSwipeActions()) {
+ swipeViewHolder.addSwipeAction(swipeAction)
+ }
+ if (null != mClickListener) {
+ itemView.setOnClickListener {
+ mClickListener!!.onItemClick(itemView, swipeViewHolder.adapterPosition)
+ }
+ }
+ if (null != mLongClickListener) {
+ itemView.setOnLongClickListener {
+ mLongClickListener!!.onItemLongClick(itemView, swipeViewHolder.adapterPosition)
+ true
+ }
+ }
+ return swipeViewHolder
+ }
+ }
+
+ override fun onBindViewHolder(holder: QMUISwipeViewHolder, position: Int) {
+ if (mData.size > 0) bindData(holder, position, mData[position])
+ }
+
+ /**
+ * 判断是否是空布局
+ */
+ private fun isEmptyPosition(position: Int): Boolean {
+ val count = mData.size
+ return position == 0 && showEmptyView && count == 0
+ }
+
+ /**
+ * 设置空布局显示。默认显示
+ */
+ private fun showEmptyView(isShow: Boolean) {
+ if (isShow != showEmptyView) {
+ showEmptyView = isShow
+ notifyDataSetChanged()
+ }
+ }
+
+ override fun getItemCount() = if (mData.size == 0 && showEmptyView) 1 else mData.size
+
+ override fun getItemViewType(position: Int) =
+ if (isEmptyPosition(position)) mViewTypeEmpty else mViewTypeItem
+
+ fun setData(list: MutableList?) {
+ if (list != null) {
+ mData = list
+ //出现没有数据就显示空布局
+ if (mData.size == 0) {
+ showEmptyView(true)
+ }
+ }
+ }
+
+ fun getData() = mData
+
+ fun remove(oldList: MutableList, pos: Int): MutableList {
+ val newList: MutableList = oldList.toMutableList()
+ newList.removeAt(pos)
+ return newList
+ }
+
+ fun getItem(pos: Int) = mData[pos]
+
+ /**
+ * 设置显示空布局 等于0不显示空布局
+ */
+ abstract fun getEmptyLayoutId(viewType: Int): Int
+
+ //菜单集合
+ abstract fun getSwipeActions(): MutableList
+ abstract fun getItemLayoutId(viewType: Int): Int
+ abstract fun bindData(holder: QMUISwipeViewHolder?, position: Int, item: T)
+
+ fun setOnItemClickListener(listener: BaseRecyclerAdapter.OnItemClickListener?) {
+ mClickListener = listener
+ }
+
+ fun setOnItemLongClickListener(listener: BaseRecyclerAdapter.OnItemLongClickListener?) {
+ mLongClickListener = listener
+ }
+
+ fun setOnAgainClickListener(listener: BaseRecyclerAdapter.OnAgainClickListener?) {
+ mAgainClickListener = listener
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseView.kt b/app/src/main/java/com/abbidot/tracker/base/BaseView.kt
new file mode 100644
index 0000000..ef561ee
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseView.kt
@@ -0,0 +1,51 @@
+package com.abbidot.tracker.base
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.View
+import com.abbidot.baselibrary.util.AppUtils
+
+/**
+ *Created by .yzq on 2024/10/11/011.
+ * @link
+ * @description:
+ */
+open class BaseView : View {
+
+ lateinit var mContext: Context
+ var mWidth = 0
+ var mHeight = 0
+ var mValue = 0
+ var mStrokeWidth = 0f
+
+ lateinit var mPaint: Paint
+
+ constructor(context: Context) : super(context)
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
+ context, attrs, defStyleAttr
+ )
+
+ open fun init(context: Context, attrs: AttributeSet?) {
+ mContext = context
+
+ //禁用硬件加速,防止返回到界面多次执行onDraw
+ setLayerType(LAYER_TYPE_SOFTWARE, null)
+
+ mStrokeWidth = AppUtils.dpToPx(1f)
+ mPaint = Paint()
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ canvas.apply {
+ startDraw(this)
+ }
+ }
+
+ open fun startDraw(canvas: Canvas) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/ActiveTimeBean.kt b/app/src/main/java/com/abbidot/tracker/bean/ActiveTimeBean.kt
new file mode 100644
index 0000000..68f5651
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/ActiveTimeBean.kt
@@ -0,0 +1,40 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/3/15/015.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class ActiveTimeBean(
+ var activeId: String,
+ var activeTime: Int,
+ var goalTime: Int,
+ var goal: Int,
+ var calories: Double,
+ var dayTime: String,
+ var deviceId: String,
+ var distance: Double,
+ var lickCounts: Int,
+ var persisted: Int,
+ var scratchCounts: Int,
+ var steps: Long,
+ var timeZone: Int,
+ var updateDate: String,
+ var vomitCount: Int,
+ var avgActiveTime: Int,
+ var avgSleepTime: Int,
+ var totalTimes: Int,
+ var totalDistance: Double,
+ var activeValue: String,
+ var avgCalories: Int,
+ var sevenDatas: MutableList?,
+ var thirtyDatas: MutableList?,
+) : Parcelable {
+ constructor() : this(
+ "", 0, 0, 0, 0.0, "", "", 0.0, 0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0.0, "", 0, null, null
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/AlipayOrderBean.kt b/app/src/main/java/com/abbidot/tracker/bean/AlipayOrderBean.kt
new file mode 100644
index 0000000..d750436
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/AlipayOrderBean.kt
@@ -0,0 +1,10 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2022/7/29/029.
+ * @link
+ * @description:微信支付预支付订单
+ */
+data class AlipayOrderBean(val orderString: String) {
+ constructor() : this("")
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/BleReportDataBean.kt b/app/src/main/java/com/abbidot/tracker/bean/BleReportDataBean.kt
new file mode 100644
index 0000000..c972358
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/BleReportDataBean.kt
@@ -0,0 +1,78 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2025/3/19/019.
+ * @link
+ * @description:
+ */
+data class BleReportDataBean(
+ var mac: String,
+ var haveDeviceStateData: Boolean,
+ var updateTime: Long,
+ var latLonUpdateTime: Long,
+ var powerSwitch: Int,
+ var lteSignal: Int,
+ var gpsSignal: Int,
+ var batteryLevel: Int,
+ var gnssInterval: Int,
+ var ledSwitch: Int,
+ var ledMode: Int,
+ var ledRedValue: Int,
+ var ledGreenValue: Int,
+ var ledBlueValue: Int,
+ var liveFlag: Int,
+ var inSafeZone: Int,
+ var inNoGoZone: Int,
+ var cFencesId: String,
+ var inWifiZone: Int,
+ var wiFiZoneMac: String,
+ var haveLocationData: Boolean,
+ var locationMode: Int,
+ var locationList: MutableList?,
+ var haveActiveSleepData: Boolean,
+ var year: Int,
+ var month: Int,
+ var day: Int,
+ var activeTime: Long,
+ var steps: Long,
+ var timeZone: Int,
+ var cTime: Int,
+ var cActiveTime: Int,
+ var cSleepTime: Int
+) {
+ constructor() : this(
+ "",
+ false,
+ 0L,
+ 0L,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ "",
+ 0,
+ "",
+ false,
+ 0,
+ null,
+ false,
+ 0,
+ 0,
+ 0,
+ 0L,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ )
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/BleTrackDeviceBean.kt b/app/src/main/java/com/abbidot/tracker/bean/BleTrackDeviceBean.kt
new file mode 100644
index 0000000..d9e1bd2
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/BleTrackDeviceBean.kt
@@ -0,0 +1,15 @@
+package com.abbidot.tracker.bean
+
+import com.abbidot.baselibrary.constant.ConState
+import com.clj.fastble.data.BleDevice
+
+/**
+ *Created by .yzq on 2022/5/27/027.
+ * @link
+ * @description:已绑定添加的设备实体类
+ */
+data class BleTrackDeviceBean(var mac: String,
+ var bleDevice: BleDevice?,
+ @ConState var conState: Int) {
+ constructor() : this("", null, ConState.DISCONNECTED)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/CountryCodeBean.kt b/app/src/main/java/com/abbidot/tracker/bean/CountryCodeBean.kt
new file mode 100644
index 0000000..aae044f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/CountryCodeBean.kt
@@ -0,0 +1,8 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/5/23/023.
+ * @link
+ * @description:
+ */
+data class CountryCodeBean(var countryCode: Int)
diff --git a/app/src/main/java/com/abbidot/tracker/bean/CreditCardBean.kt b/app/src/main/java/com/abbidot/tracker/bean/CreditCardBean.kt
new file mode 100644
index 0000000..08a4433
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/CreditCardBean.kt
@@ -0,0 +1,30 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Ignore
+import androidx.room.PrimaryKey
+import com.abbidot.tracker.database.MyDatabase
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/4/1/001.
+ * @link
+ * @description:保存用户输入信用卡
+ */
+@Parcelize
+@Entity(tableName = MyDatabase.CreditCardTableName)
+data class CreditCardBean(
+ @PrimaryKey @ColumnInfo var cardNumber: String,
+ @ColumnInfo var firstName: String,
+ @ColumnInfo var lastName: String,
+ @ColumnInfo var cardName: String,
+ @ColumnInfo var expirationDate: String,
+ @ColumnInfo var cvv: String,//信用卡验证值(Card Verification Value)
+ @ColumnInfo var countryCode: String,
+ @ColumnInfo var isPrimary: Boolean,
+ @Ignore var checked: Boolean = false
+) : Parcelable {
+ constructor() : this("", "", "", "", "", "", "USA", false, false)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/DFUStateBean.kt b/app/src/main/java/com/abbidot/tracker/bean/DFUStateBean.kt
new file mode 100644
index 0000000..475cf6c
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/DFUStateBean.kt
@@ -0,0 +1,12 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2023/3/23/023.
+ * @link
+ * @description:
+ */
+data class DFUStateBean(var stateName: String, var progress: Int, var filePath: String) {
+ constructor() : this("", 0, "")
+ constructor(stateName: String, progress: Int) : this(stateName, progress, "")
+ constructor(stateName: String) : this(stateName, 0, "")
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/DataBean.kt b/app/src/main/java/com/abbidot/tracker/bean/DataBean.kt
new file mode 100644
index 0000000..e075f95
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/DataBean.kt
@@ -0,0 +1,43 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import com.abbidot.tracker.constant.MultipleEntity
+import com.chad.library.adapter.base.entity.MultiItemEntity
+import kotlinx.parcelize.Parcelize
+import kotlinx.parcelize.IgnoredOnParcel
+
+/**
+ *Created by .yzq on 2021/12/20/020.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class DataBean(
+ var id: String,
+ var name: String,
+ var value: String,
+ var imageId: Int,
+ var state: Int,
+ var selectImageId: Int,
+ var unit: String,
+ var selected: Boolean = false,
+ var checked: Boolean = false,
+ var menuType: Int
+) : MultiItemEntity, Parcelable {
+
+ //设置空的构造方法
+ constructor() : this("", "", "", 0, 0, 0, "", false, false, MultipleEntity.TEXT)
+
+ constructor(name: String, value: String) : this(
+ "", name, value, 0, 0,0, "", false, false, MultipleEntity.TEXT
+ )
+
+ //设置多个构造方法
+ constructor(name: String, value: String, imageId: Int, unit: String) : this(
+ "", name, value, imageId, 0, 0, unit, false, false, MultipleEntity.TEXT
+ )
+
+ @IgnoredOnParcel
+ @MultipleEntity
+ override val itemType = menuType
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/DeviceBean.kt b/app/src/main/java/com/abbidot/tracker/bean/DeviceBean.kt
new file mode 100644
index 0000000..07bdbf4
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/DeviceBean.kt
@@ -0,0 +1,53 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Ignore
+import com.abbidot.baselibrary.constant.ConState
+import com.abbidot.baselibrary.constant.DeviceType
+import com.abbidot.tracker.base.BaseDiffBean
+import com.abbidot.tracker.database.MyDatabase
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2021/11/8/008.
+ * @link
+ * @description:连接保存的设备表
+ */
+// 定义表名称,SQLite 中的表名称不区分大小写,2个主键
+@Entity(tableName = MyDatabase.DeviceTableName, primaryKeys = ["deviceOutId", "deviceId"])
+@Parcelize
+data class DeviceBean(//@PrimaryKey(autoGenerate = true) var id: Long,//autoGenerate = true 自动增长分配ID
+ @ColumnInfo @DeviceType var type: Int,//设备类型
+ @ColumnInfo var deviceName: String,
+ @ColumnInfo var deviceOutId: String,
+ @ColumnInfo var deviceId: String,
+ @ColumnInfo var shared: Int, //0=没有分享,1=是授权分享的
+ @ColumnInfo var batteryCapacity: Int,
+ @ColumnInfo var ledSwitch: Int,
+ @ColumnInfo @ConState var conState: Int,//连接状态
+ @ColumnInfo var macId: String,
+ @ColumnInfo var deviceInfoId: String,
+ @ColumnInfo var surplusDays: Int,
+ @ColumnInfo var gnssSignal: Int,
+ @ColumnInfo var lteSignal: Int,
+ @ColumnInfo var turnOff: Int,
+ @ColumnInfo var lightMode: Int,
+ @Ignore var pet: PetBean?) : BaseDiffBean(), Parcelable {
+ // 如果某个实体中有您不想保留的字段,则可以使用 @Ignore 为这些字段添加注释
+
+ //设置空的构造方法
+ constructor() : this(DeviceType.TYPE_ONE, "", "", "", 0, 0, 0, ConState.DISCONNECTED, "", "", 0,
+ 0, 0, 0, 0, null)
+
+ override fun isSameObject(other: Any): Boolean {
+ val oldItem = other as DeviceBean
+ return deviceId == oldItem.deviceId
+ }
+
+ override fun hasSameContent(other: Any): Boolean {
+ val oldItem = other as DeviceBean
+ return oldItem.deviceOutId == deviceOutId && oldItem.batteryCapacity == batteryCapacity && oldItem.ledSwitch == ledSwitch && oldItem.pet == pet && oldItem.gnssSignal == gnssSignal && oldItem.lteSignal == lteSignal
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/DeviceDetailBean.kt b/app/src/main/java/com/abbidot/tracker/bean/DeviceDetailBean.kt
new file mode 100644
index 0000000..349ecbd
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/DeviceDetailBean.kt
@@ -0,0 +1,20 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/2/28/028.
+ * @link
+ * @description:设备详情
+ */
+@Parcelize
+data class DeviceDetailBean(var deviceOutId: String,
+ var deviceId: String,
+ var macId: String,
+ var pet: PetBean?,
+ var fenceCount: Int,
+ var surplusDays: Int,
+ var familieCount: Int,var deviceInfo:DeviceInfoBean?) : Parcelable {
+ constructor() : this("", "", "", null, 0, 0,0,null)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/DeviceInfoBean.kt b/app/src/main/java/com/abbidot/tracker/bean/DeviceInfoBean.kt
new file mode 100644
index 0000000..b574afc
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/DeviceInfoBean.kt
@@ -0,0 +1,22 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class DeviceInfoBean(var deviceInfoId: String,
+ var red: Int,
+ var green: Int,
+ var blue: Int,
+ //第一个 是:几分钟设备上报。2信号强度,3电量 4设备关机还是开机 5 light登打开还是关闭。5 wifi强度
+ var gnssInterval: Int,
+ var gnssSignal: Int,
+ var batteryLevel: Int,
+ var turnOff: Int,
+ var ledSwitch: Int,
+ var wifiSignal: Int,
+ //当前LTE网络信号
+ var lteSignal: Int,
+ var lightMode: Int) : Parcelable {
+ constructor() : this("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/FamilyBean.kt b/app/src/main/java/com/abbidot/tracker/bean/FamilyBean.kt
new file mode 100644
index 0000000..5b99359
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/FamilyBean.kt
@@ -0,0 +1,39 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import com.abbidot.tracker.base.BaseDiffBean
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/2/28/028.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class FamilyBean(
+ var acceptEmail: String,
+ var deviceId: String,
+ var familyId: String,
+ var imgurl: String,
+ var inviteDate: String,
+ var sendEmail: String,
+ var status: Int,//设备的分享状态 1 是分享成功 0 分享中 2 已拒绝
+ var userId: String,
+ var relation: Int,//关系 1 Family 2 friend 3 love 4 colleague
+ var avatar: Int,//头像 1 男生 2 女生 3 未知
+ var userName: String,
+ var petId: String,
+ var petName: String
+) : Parcelable, BaseDiffBean() {
+ constructor() : this("", "", "", "", "", "", 0, "", 1, 1, "", "", "")
+
+ override fun isSameObject(other: Any): Boolean {
+ val oldItem = other as FamilyBean
+ return familyId == oldItem.familyId
+ }
+
+ override fun hasSameContent(other: Any): Boolean {
+ val oldItem = other as FamilyBean
+ return oldItem.imgurl == imgurl && oldItem.acceptEmail == acceptEmail
+ }
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/FamilyPetBean.kt b/app/src/main/java/com/abbidot/tracker/bean/FamilyPetBean.kt
new file mode 100644
index 0000000..84bca9d
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/FamilyPetBean.kt
@@ -0,0 +1,13 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2022/3/10/010.
+ * @link
+ * @description:
+ */
+data class FamilyPetBean(var petName: String,
+ var petImgurl: String,
+ var deviceOutId: String,
+ var families: MutableList?) {
+ constructor() : this("", "", "", null)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/FencesBean.kt b/app/src/main/java/com/abbidot/tracker/bean/FencesBean.kt
new file mode 100644
index 0000000..da62399
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/FencesBean.kt
@@ -0,0 +1,96 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import com.abbidot.tracker.base.BaseDiffBean
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/2/28/028.
+ * @link
+ * @description:围栏
+ */
+@Parcelize
+data class FencesBean(
+ var deviceId: String,
+ var deviceServiceId: String,
+ var fenceId: String,
+ var name: String,
+ var address: String,
+ var imgurl: String,
+ var isOn: Int,
+ var radius: Int,
+ var longitude: Double,
+ var latitude: Double,
+ var fenceShapeType: Int,// fenceShapeType 围栏类型,1是圆形,2是矩形 3是六边形
+ var fenceType: Int,//围栏类型,1是Safe Zone,2是No Go Zone
+ var fenceNameType: Int,//名称类型,1是home,2是Office,3是Garden,4是Park,5是Play,6是Garage,7是vegetable garden,8是River
+ var longitudeA: Double,
+ var latitudeA: Double,
+ var longitudeB: Double,
+ var latitudeB: Double,
+ var longitudeC: Double,
+ var latitudeC: Double,
+ var longitudeD: Double,
+ var latitudeD: Double,
+ var longitudeE: Double,
+ var latitudeE: Double,
+ var longitudeF: Double,
+ var latitudeF: Double,
+ var longitudeCenter: Double,
+ var latitudeCenter: Double,
+ var ancillaryLatitude: Double,
+ var ancillaryLongitude: Double,
+ var ancillaryOtherLatitude: Double,
+ var ancillaryOtherLongitude: Double,
+ var longDistance: Int,
+ var shortDistance: Int,
+ var startDrag: Boolean//围栏形状是否开始拖动
+) : Parcelable, BaseDiffBean() {
+ constructor() : this(
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ 0,
+ 0,
+ 0.0,
+ 0.0,
+ 1,
+ 1,
+ 1,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ false
+ )
+
+ override fun isSameObject(other: Any): Boolean {
+ val oldItem = other as FencesBean
+ return oldItem.fenceId == fenceId
+ }
+
+ override fun hasSameContent(other: Any): Boolean {
+ val oldItem = other as FencesBean
+ return oldItem.isOn == isOn && oldItem.name == name && oldItem.imgurl == imgurl && oldItem.address == address && oldItem.fenceType == fenceType
+ }
+
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/FirmwareBean.kt b/app/src/main/java/com/abbidot/tracker/bean/FirmwareBean.kt
new file mode 100644
index 0000000..6821e4e
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/FirmwareBean.kt
@@ -0,0 +1,16 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2023/3/22/022.
+ * @link
+ * @description:固件信息
+ */
+data class FirmwareBean(
+ var deviceName: String,
+ var version: String,
+ var remark: String,
+ var fileName: String,
+ var firmwareUrl: String,
+ var mac: String,
+ var firmwareSize: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/GetFencesBean.kt b/app/src/main/java/com/abbidot/tracker/bean/GetFencesBean.kt
new file mode 100644
index 0000000..99f061b
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/GetFencesBean.kt
@@ -0,0 +1,19 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2024/4/25/025.
+ * @link
+ * @description:获取围栏数据返回
+ */
+@Parcelize
+data class GetFencesBean(
+ var latitude: Double,
+ var longitude: Double,
+ var normalFenceList: MutableList?,
+ var nogoFenceList: MutableList?
+) : Parcelable {
+ constructor() : this(0.0, 0.0, null, null)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/HistoryDataBean.kt b/app/src/main/java/com/abbidot/tracker/bean/HistoryDataBean.kt
new file mode 100644
index 0000000..3e56793
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/HistoryDataBean.kt
@@ -0,0 +1,31 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import com.abbidot.tracker.constant.ConstantInt
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/3/16/016.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class HistoryDataBean(var dayTime: String,
+ var deviceId: String,
+ var deviceInfoId: String,
+ var historyPointId: String,
+ var latitude: Double,
+ var longitude: Double,
+ var address: String,
+ var positionMode: Int,
+ var timeStamp: Long,
+ var ledSwitch: Int,
+ var gnssSignal: Int,
+ var batteryLevel: Int,
+ var lightMode: Int,
+ @ConstantInt var inFance: Int,
+ var petName: String,
+ var petImgurl: String) : Parcelable {
+ constructor() : this("", "", "", "", 0.0, 0.0, "", 0, 0L, 0, 0, 0, 0, ConstantInt.GoodZone, "",
+ "")
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/HomeDataBean.kt b/app/src/main/java/com/abbidot/tracker/bean/HomeDataBean.kt
new file mode 100644
index 0000000..47fa20e
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/HomeDataBean.kt
@@ -0,0 +1,14 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2022/3/15/015.
+ * @link
+ * @description:
+ */
+data class HomeDataBean(
+ var activeTime: ActiveTimeBean?,
+ var sleepTime: SleepTimeBean?,
+ var updateTime: Long
+) {
+ constructor() : this(null, null, 0)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/InviteInfoBean.kt b/app/src/main/java/com/abbidot/tracker/bean/InviteInfoBean.kt
new file mode 100644
index 0000000..f2ce9a3
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/InviteInfoBean.kt
@@ -0,0 +1,10 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/12/4/004.
+ * @link
+ * @description:设备邀请信息
+ */
+data class InviteInfoBean(
+ var deleteArray: MutableList, var inviteArray: MutableList
+)
diff --git a/app/src/main/java/com/abbidot/tracker/bean/LKSimListBean.kt b/app/src/main/java/com/abbidot/tracker/bean/LKSimListBean.kt
new file mode 100644
index 0000000..ae32fac
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/LKSimListBean.kt
@@ -0,0 +1,16 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2023/7/10/010.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class LKSimListBean(
+ var partnerCode: String, var planList: MutableList?
+) : Parcelable {
+ constructor() : this("", null)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/LKSimPriceBean.kt b/app/src/main/java/com/abbidot/tracker/bean/LKSimPriceBean.kt
new file mode 100644
index 0000000..d1fb76c
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/LKSimPriceBean.kt
@@ -0,0 +1,24 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2023/7/7/007.
+ * @link
+ * @description:领科sim卡套餐价格
+ */
+@Parcelize
+data class LKSimPriceBean(
+ var autoRenewal: String,
+ var currency: String,
+ var currencySymbol: String,
+ var discountPriceCNY: String,
+ var discountPriceUSD: Double,
+ var orderPeriod: String,
+ var packageType: String,
+ var specifications: String,
+ var specifiedNameLabel: String
+) : Parcelable {
+ constructor() : this("", "", "", "", 0.0, "", "", "", "")
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/LKSimSetMealBean.kt b/app/src/main/java/com/abbidot/tracker/bean/LKSimSetMealBean.kt
new file mode 100644
index 0000000..6fd90ad
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/LKSimSetMealBean.kt
@@ -0,0 +1,27 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2023/7/7/007.
+ * @link
+ * @description:领科sim卡套餐
+ */
+@Parcelize
+data class LKSimSetMealBean(
+ var currency: String,
+ var currencyId: String,
+ var currencySymbol: String,
+ var languageCode: String,
+ var minOrderPeriod: String,
+ var packageCode: String,
+ var servicePlanCode: String,
+ var servicePlanDetailsDesc: String,
+ var servicePlanShortDesc: String,
+ var servicePlanShowName: String,
+ var specAndPriceList: MutableList?,
+ var stripeCoupon: String
+) : Parcelable {
+ constructor() : this("", "", "", "", "", "", "", "", "", "", null, "")
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/LabelBean.kt b/app/src/main/java/com/abbidot/tracker/bean/LabelBean.kt
new file mode 100644
index 0000000..3f6cb8d
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/LabelBean.kt
@@ -0,0 +1,25 @@
+package com.abbidot.tracker.bean
+
+import com.abbidot.tracker.base.BaseDiffBean
+
+/**
+ *Created by .yzq on 2021/12/21/021.
+ * @link
+ * @description:宠物标签
+ */
+data class LabelBean(var name: String, var check: Boolean) : BaseDiffBean() {
+
+ //设置空的构造方法
+ constructor() : this("", false)
+ constructor(name: String) : this(name, false)
+
+ override fun isSameObject(other: Any): Boolean {
+ val oldItem = other as LabelBean
+ return oldItem.name == name
+ }
+
+ override fun hasSameContent(other: Any): Boolean {
+ val oldItem = other as LabelBean
+ return oldItem.name == name && oldItem.check == check
+ }
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/LiveDataBean.kt b/app/src/main/java/com/abbidot/tracker/bean/LiveDataBean.kt
new file mode 100644
index 0000000..a84cd5c
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/LiveDataBean.kt
@@ -0,0 +1,12 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/4/28/028.
+ * @link
+ * @description:
+ */
+data class LiveDataBean(
+ var livePoints: MutableList?, var deviceInfo: MapDeviceBean?
+) {
+ constructor() : this(null, null)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/MapDeviceBean.kt b/app/src/main/java/com/abbidot/tracker/bean/MapDeviceBean.kt
new file mode 100644
index 0000000..96f1dab
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/MapDeviceBean.kt
@@ -0,0 +1,70 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import com.abbidot.tracker.constant.ConstantInt
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class MapDeviceBean(
+ var deviceId: String,
+ var deviceOutId: String,
+ var baseId: String,
+ var inSafeZone: Int,
+ var gpsSignal: Int,
+ var batteryLevel: Int,
+ var longitude: Double,
+ var latitude: Double,
+ var ledSwitch: Int,
+ var gnssInterval: Int,
+ var liveTime: Int,
+ var liveFlag: Int,
+ var updateTime: Long,
+ var latLonUpdateTime: Long,
+ var lteSignal: Int,
+ var deviceMacId: String,
+ var deviceServerId: String,
+ var powerSwitch: Int,
+ var inNoGoZone: Int,
+ var speed: Float,
+ var inWifiZone: Int,
+ var ledMode: Int,
+ var ledRedValue: Int,
+ var ledGreenValue: Int,
+ var ledBlueValue: Int,
+ var fences: MutableList?,
+ var wifiZones: MutableList?,
+ var startTime: String,
+ var endTime: String
+) : Parcelable {
+ constructor() : this(
+ "",
+ "",
+ "",
+ ConstantInt.GoodZone,
+ 0,
+ 0,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ 0,
+ 0,
+ System.currentTimeMillis(),
+ System.currentTimeMillis(),
+ 0,
+ "",
+ "",
+ 0,
+ 0,
+ 0f,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ "",
+ ""
+ )
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/MenuTxtBean.kt b/app/src/main/java/com/abbidot/tracker/bean/MenuTxtBean.kt
new file mode 100644
index 0000000..63580d4
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/MenuTxtBean.kt
@@ -0,0 +1,39 @@
+package com.abbidot.tracker.bean
+
+import com.abbidot.tracker.constant.MultipleEntity
+import com.chad.library.adapter.base.entity.MultiItemEntity
+
+/**
+ *Created by .yzq on 2021/12/20/020.
+ * @link
+ * @description: 菜单显示
+ */
+data class MenuTxtBean(
+ var menuName: String,
+ var menuValue: String,
+ var imageId: Int,
+ var colorRedId: Int,
+ var imageUrl: String,
+ var isSwitch: Boolean,
+ @MultipleEntity val menuType: Int
+) : MultiItemEntity {
+
+ //设置空的构造方法
+ constructor(@MultipleEntity menuType: Int) : this("", "", 0, 0, "", false, menuType)
+
+ //设置多个构造方法
+ constructor(menuName: String, menuValue: String, @MultipleEntity menuType: Int) : this(
+ menuName, menuValue, 0, 0, "", false, menuType
+ )
+
+ constructor(menuName: String, menuValue: String) : this(
+ menuName, menuValue, 0, 0, "", false, MultipleEntity.TEXT
+ )
+
+ constructor(menuName: String, imageId: Int, menuValue: String) : this(
+ menuName, menuValue, imageId, 0, "", false, MultipleEntity.TEXT
+ )
+
+ @MultipleEntity
+ override val itemType = menuType
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/MessageBean.kt b/app/src/main/java/com/abbidot/tracker/bean/MessageBean.kt
new file mode 100644
index 0000000..4b8ce1f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/MessageBean.kt
@@ -0,0 +1,28 @@
+package com.abbidot.tracker.bean
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Ignore
+import com.abbidot.tracker.constant.MultipleEntity
+import com.abbidot.tracker.database.MyDatabase
+
+/**
+ *Created by .yzq on 2022/2/24/024.
+ * @link
+ * @description:消息列表
+ */
+@Entity(tableName = MyDatabase.MessageTableName, primaryKeys = ["messageId"])
+data class MessageBean(
+ @ColumnInfo var messageId: String,
+ @ColumnInfo var title: String,
+ @ColumnInfo var message: String,
+ @ColumnInfo var sendTime: String,
+ @ColumnInfo var messageType: Int,
+ @ColumnInfo var imgUrl: String,
+ @ColumnInfo var isRead: Boolean,
+ @Ignore @MultipleEntity var isContainImg: Int,
+ @Ignore var isSelect: Boolean
+) {
+ constructor() : this("", "", "", "", 1, "", false, MultipleEntity.TEXT, false)
+}
+
diff --git a/app/src/main/java/com/abbidot/tracker/bean/NotificationBean.kt b/app/src/main/java/com/abbidot/tracker/bean/NotificationBean.kt
new file mode 100644
index 0000000..0e81b68
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/NotificationBean.kt
@@ -0,0 +1,11 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/9/26/026.
+ * @link
+ * @description:
+ */
+
+data class NotificationBean(
+ var enabled: Int, var notificationType: Int, var status: Int, var userId: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/OrderBean.kt b/app/src/main/java/com/abbidot/tracker/bean/OrderBean.kt
new file mode 100644
index 0000000..71d1718
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/OrderBean.kt
@@ -0,0 +1,12 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2022/3/31/031.
+ * @link
+ * @description:
+ * @param isCanRefund 是否可以退款 1 是可以 0 是不可以
+ */
+data class OrderBean(
+ var orderId: String, var orderNo: String, var availableOrder: Int,//判断套餐是否可用或过期,1是可用 0不可用
+ var isCanRefund: Int
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/PackageBean.kt b/app/src/main/java/com/abbidot/tracker/bean/PackageBean.kt
new file mode 100644
index 0000000..0856c69
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/PackageBean.kt
@@ -0,0 +1,25 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2024/9/5/005.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class PackageBean(
+ var mealId: String,
+ var planName: String,
+ var mealUnit: String,
+ var planCategory: String,
+ var period: Int,
+ var popularType: Int,
+ var discountedPrice: Double,
+ var autoRenewPrice: Double,
+ var planPrice: Double,
+ var discount: Int,
+ var active: Int,
+ var selected: Boolean
+) : Parcelable
diff --git a/app/src/main/java/com/abbidot/tracker/bean/PackageBenefitsBean.kt b/app/src/main/java/com/abbidot/tracker/bean/PackageBenefitsBean.kt
new file mode 100644
index 0000000..4484813
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/PackageBenefitsBean.kt
@@ -0,0 +1,8 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/9/5/005.
+ * @link
+ * @description:
+ */
+data class PackageBenefitsBean(var title: String, var status: Int)
diff --git a/app/src/main/java/com/abbidot/tracker/bean/PackageTypeBean.kt b/app/src/main/java/com/abbidot/tracker/bean/PackageTypeBean.kt
new file mode 100644
index 0000000..4ee7f82
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/PackageTypeBean.kt
@@ -0,0 +1,14 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/9/5/005.
+ * @link
+ * @description:
+ */
+data class PackageTypeBean(
+ var price: Double,
+ var name: String,
+ var packageId: String,
+ var list: MutableList?,
+ var selected: Boolean
+)
diff --git a/app/src/main/java/com/abbidot/tracker/bean/ParentBadgeBean.kt b/app/src/main/java/com/abbidot/tracker/bean/ParentBadgeBean.kt
new file mode 100644
index 0000000..946ec7d
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/ParentBadgeBean.kt
@@ -0,0 +1,12 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/3/6/006.
+ * @link
+ * @description:
+ */
+data class ParentBadgeBean(
+ var parentName: String, var badgeList: MutableList?, var isExpand: Boolean = false
+) {
+ constructor() : this("", null, false)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/PayResultBean.kt b/app/src/main/java/com/abbidot/tracker/bean/PayResultBean.kt
new file mode 100644
index 0000000..1fca3b0
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/PayResultBean.kt
@@ -0,0 +1,25 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import com.abbidot.tracker.constant.ConstantInt
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/3/28/028.
+ * @link
+ * @description:BraintreePal请求结果返回
+ */
+@Parcelize
+data class PayResultBean(
+ var orderId: String,
+ var tokenId: String,
+ var url: String,
+ var surplusDays: Long,
+ var expirationTime: String,
+ var deviceOutId: String,
+ var deviceId: String,
+ //设备充值类型,0=首次设备充值激活,1=已添加设备再次添加设备充值,2=给当前的设备续费或者升级套餐
+ var rechargeType: Int
+) : Parcelable {
+ constructor() : this("", "", "", 0L, "", "", "", ConstantInt.Type1)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/PetAllInfoBean.kt b/app/src/main/java/com/abbidot/tracker/bean/PetAllInfoBean.kt
new file mode 100644
index 0000000..70cefac
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/PetAllInfoBean.kt
@@ -0,0 +1,15 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/5/28/028.
+ * @link
+ * @description:
+ */
+data class PetAllInfoBean(
+ var badges: MutableList?,
+ var activity: ActiveTimeBean?,
+ var petInfo: PetBean?,
+ var invites: MutableList?
+) {
+ constructor() : this(null, null, null, null)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/PetBean.kt b/app/src/main/java/com/abbidot/tracker/bean/PetBean.kt
new file mode 100644
index 0000000..74f4141
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/PetBean.kt
@@ -0,0 +1,52 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.util.MMKVUtil
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.base.BaseDiffBean
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/2/28/028.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class PetBean(
+ var petId: String,
+ var deviceServiceId: String,
+ var petName: String,
+ var breed: String,
+ var shared: Int, //0=没有分享,1=是授权分享的
+ var petType: Int, //宠物类别 0=其他 1是狗 2是猫
+ var userId: String,
+ var imgurl: String,
+ var gender: Int,
+ var birthdayDate: String,
+ var createDate: String,
+ var weight: Float,
+ var height: Float,
+ var labels: String,
+ var deviceOutId: String,
+ var macID: String,
+ var mealType: Int,
+ var availableOrder: Int,//判断套餐是否可用或过期,1是可用 0不可用
+ var deviceId: String
+) : Parcelable, BaseDiffBean() {
+ constructor() : this(
+ "", "", "", "", 0, 1, MMKVUtil.getString(MMKVKey.UserId), "", 0, Utils.formatTime(
+ System.currentTimeMillis(), Utils.DATE_FORMAT_PATTERN_CN
+ ), "", 0f, 0f, "", "", "", 1, 1, ""
+ )
+
+ override fun isSameObject(other: Any): Boolean {
+ val oldItem = other as PetBean
+ return oldItem.petId == petId
+ }
+
+ override fun hasSameContent(other: Any): Boolean {
+ val oldItem = other as PetBean
+ return oldItem.petName == petName && oldItem.imgurl == imgurl && oldItem.deviceOutId == deviceOutId && oldItem.breed == breed && oldItem.gender == gender && oldItem.birthdayDate == birthdayDate && oldItem.petType == petType && oldItem.weight == weight && oldItem.height == height && oldItem.labels == labels
+ }
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/PointBean.kt b/app/src/main/java/com/abbidot/tracker/bean/PointBean.kt
new file mode 100644
index 0000000..b792724
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/PointBean.kt
@@ -0,0 +1,14 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/1/26/026.
+ * @link
+ * @description:
+ */
+data class PointBean(var x: Float, var y: Float) {
+ constructor() : this(0f, 0f)
+
+ override fun toString(): String {
+ return "x=$x,y=$y"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/ReceiveDeviceData.kt b/app/src/main/java/com/abbidot/tracker/bean/ReceiveDeviceData.kt
new file mode 100644
index 0000000..390cfd6
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/ReceiveDeviceData.kt
@@ -0,0 +1,12 @@
+package com.abbidot.tracker.bean
+
+import com.clj.fastble.data.BleDevice
+
+/**
+ *Created by .yzq on 2021/12/1/001.
+ * @link
+ * @description:
+ */
+data class ReceiveDeviceData(var bleDevice: BleDevice?, var data: ByteArray?, var mac: String) {
+ constructor() : this(null, null, "")
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/RechargeDeviceBean.kt b/app/src/main/java/com/abbidot/tracker/bean/RechargeDeviceBean.kt
new file mode 100644
index 0000000..a2f4c2c
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/RechargeDeviceBean.kt
@@ -0,0 +1,29 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import com.abbidot.tracker.constant.ConstantInt
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/3/25/025.
+ * @link
+ * @description:my card
+ */
+@Parcelize
+data class RechargeDeviceBean(
+ var deviceId: String,
+ var deviceOutId: String,
+ var payType: Int,//付款渠道 1 信用卡 2Paypal
+ var orderId: String,
+ var subscriptionsId: String,//取消自动续费用的id
+ var overdueDate: String,//过期日期
+ @ConstantInt var subscriptionStatus: Int,//自动续费状态
+ var pet: PetBean?,
+ var surplusDays: Int,
+ var addStatus: Int,
+ var orderStatus: Int,
+ var period: String,
+ var iccid: String
+) : Parcelable {
+ constructor() : this("", "", 0, "", "", "", ConstantInt.Close, null, 0, 0, 0, "0", "")
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/RechargeHistoryBean.kt b/app/src/main/java/com/abbidot/tracker/bean/RechargeHistoryBean.kt
new file mode 100644
index 0000000..6b3571d
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/RechargeHistoryBean.kt
@@ -0,0 +1,14 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2022/3/26/026.
+ * @link
+ * @description:
+ */
+data class RechargeHistoryBean(var cost: Float,
+ var historyId: String,
+ var payTime: String,
+ var feePackage: String,
+ var deviceOutId: String) {
+ constructor() : this(0f, "", "", "", "")
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/SetMealBean.kt b/app/src/main/java/com/abbidot/tracker/bean/SetMealBean.kt
new file mode 100644
index 0000000..75e3c6a
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/SetMealBean.kt
@@ -0,0 +1,24 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2022/3/26/026.
+ * @link
+ * @description:充值套餐列表
+ */
+@Parcelize
+data class SetMealBean(var subscriptionFee: Double,
+ var hotType: Int,//1=hot 0=普通
+ var mealId: String,
+ var name: String,
+ var createdDate: String,
+ var updateDate: String,
+ var days: Int,
+ var period: Float,
+ var planId: String,
+ var selected: Boolean,
+ var accountFee: Double) : Parcelable {
+ constructor() : this(0.0, 0, "", "", "", "", 0, 0f, "", false,0.0)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/SleepTimeBean.kt b/app/src/main/java/com/abbidot/tracker/bean/SleepTimeBean.kt
new file mode 100644
index 0000000..4f5add1
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/SleepTimeBean.kt
@@ -0,0 +1,20 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2022/3/15/015.
+ * @link
+ * @description:
+ */
+data class SleepTimeBean(
+ var dayTime: String,
+ var deviceId: String,
+ var sleepTime: Int,
+ var activeTime: Int,
+ var sleepId: String,
+ var sleepValue: String,
+ var avgSleepTime: Int,
+ var sevenDatas: MutableList? = null,
+ var thirtyDatas: MutableList? = null
+) {
+ constructor() : this("", "", 0, 0, "", "", 0, null, null)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/StripeSubscriptionPriceBean.kt b/app/src/main/java/com/abbidot/tracker/bean/StripeSubscriptionPriceBean.kt
new file mode 100644
index 0000000..7bd8364
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/StripeSubscriptionPriceBean.kt
@@ -0,0 +1,10 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2023/7/20/020.
+ * @link
+ * @description:
+ */
+data class StripeSubscriptionPriceBean(var customerId: String, var priceId: String) {
+ constructor() : this("", "")
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/SubscriptionsOrderBean.kt b/app/src/main/java/com/abbidot/tracker/bean/SubscriptionsOrderBean.kt
new file mode 100644
index 0000000..b3d735f
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/SubscriptionsOrderBean.kt
@@ -0,0 +1,98 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2024/9/4/004.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class SubscriptionsOrderBean(
+ var annualCarePrice: Double,
+ var annualCareType: Int,
+ var couponCode: String,
+ var couponPrice: Double,
+ var createTime: String,
+ var customerId: String,
+ var deviceId: String,
+ var deviceOutId: String,
+ var enabled: Int,
+ var id: String,
+ var mealDesc: String,
+ var mealId: String,
+ var mealName: String,
+ var mealPeriod: Int,
+ var mealPrice: Double,
+ var mealDiscountPrice: Double,
+ var orderNum: String,
+ var orderStatus: Int,//0支付取消 1支付成功 2支付失败 3待支付 4申请审核中 5退款中 6退款成功 7退款失败 8审核失败
+ var payTime: String,
+ var payType: Int,
+ var planCategory: String,
+ var planId: String,
+ var priceId: String,
+ var reactivatePrice: Double,
+ var reactivation: Int,
+ var simId: String,
+ var subscriptionId: String,
+ var subscriptionStatus: Int,
+ var surplusDays: Long,
+ var autoRenewPrice: Double,
+ var tax: Double,
+ var totalAmountWithTax: Double,
+ var transactionId: String,
+ var updateTime: String,
+ var useCoupon: Int,
+ var userId: String,
+ var mealUnit: String,
+ var username: String,
+ var iccid: String,
+ var endTime: Long,
+ var isUpdateOrder: Int = 0//是否是升级订单 1:是 0:否
+) : Parcelable {
+ constructor() : this(
+ 0.0,
+ 0,
+ "",
+ 0.0,
+ "",
+ "",
+ "",
+ "",
+ 0,
+ "",
+ "",
+ "",
+ "",
+ 0,
+ 0.0,
+ 0.0,
+ "",
+ 0,
+ "",
+ 0,
+ "",
+ "",
+ "",
+ 0.0,
+ 0,
+ "",
+ "",
+ 0,
+ 0L,
+ 0.0,
+ 0.0,
+ 0.0,
+ "",
+ "",
+ 0,
+ "",
+ "",
+ "",
+ "",
+ 0L,
+ 0
+ )
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/UserBean.kt b/app/src/main/java/com/abbidot/tracker/bean/UserBean.kt
new file mode 100644
index 0000000..c9f184c
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/UserBean.kt
@@ -0,0 +1,26 @@
+package com.abbidot.tracker.bean
+
+import com.abbidot.tracker.constant.ConstantInt
+
+/**
+ *Created by .yzq on 2022/2/18/018.
+ * @link
+ * @description:登录成功返回用户信息
+ */
+data class UserBean(
+ var userId: String,
+ var email: String,
+ var token: String,
+ var userName: String,
+ var wxId: String,
+ //0没有绑定手机号 1绑定了
+ var status: Int,
+ var isBindDevice: Int, //是否绑定了设备 0未绑定 1绑定
+ var isBindPet: Int, //是否绑定了宠物 0未绑定 1绑定
+ var isExistNewInvite: Int, //是否有被邀请的设备 0没有 1有
+ var measurementUnitType: Int//1:Imperial 2:Metric
+) {
+
+ //设置空的构造方法
+ constructor() : this("", "", "", "", "", 0, 0, 0, 0, ConstantInt.Type1)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/UserInfoBean.kt b/app/src/main/java/com/abbidot/tracker/bean/UserInfoBean.kt
new file mode 100644
index 0000000..468bcce
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/UserInfoBean.kt
@@ -0,0 +1,37 @@
+package com.abbidot.tracker.bean
+
+import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.util.MMKVUtil
+
+/**
+ *Created by .yzq on 2022/2/18/018.
+ * @link
+ * @description:用户信息
+ */
+data class UserInfoBean(
+ var userId: String,
+ var email: String,
+ var userName: String,
+ var imgurl: String,
+ var phone: String,
+ var location: String,
+ var gender: Int,
+ var birthdayDate: String,
+ var deviceCount: Int,
+ val countryCode: String
+// var pets: MutableList?
+) {
+
+ constructor() : this(
+ MMKVUtil.getString(MMKVKey.UserId),
+ MMKVUtil.getString(MMKVKey.Email),
+ "",
+ "",
+ "",
+ "",
+ 1,
+ "",
+ 0,
+ ""
+ )
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/WXPayOrderBean.kt b/app/src/main/java/com/abbidot/tracker/bean/WXPayOrderBean.kt
new file mode 100644
index 0000000..a40bae6
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/WXPayOrderBean.kt
@@ -0,0 +1,16 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2022/7/29/029.
+ * @link
+ * @description:微信支付预支付订单
+ */
+data class WXPayOrderBean(val appid: String,
+ val noncestr: String,
+ val packageStr: String,
+ val partnerid: String,
+ val prepayid: String,
+ val sign: String,
+ val timestamp: String) {
+ constructor() : this("", "", "", "", "", "", "")
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/bean/WiFiBean.kt b/app/src/main/java/com/abbidot/tracker/bean/WiFiBean.kt
new file mode 100644
index 0000000..e3660a5
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/WiFiBean.kt
@@ -0,0 +1,14 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2024/6/4/004.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class WiFiBean(
+ var id: Int, var name: String, var mac: String, var signal: Int, var auth_type: Int
+) : Parcelable
diff --git a/app/src/main/java/com/abbidot/tracker/bean/WiFiBleListBean.kt b/app/src/main/java/com/abbidot/tracker/bean/WiFiBleListBean.kt
new file mode 100644
index 0000000..71b9440
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/WiFiBleListBean.kt
@@ -0,0 +1,8 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/6/4/004.
+ * @link
+ * @description:获取设备蓝牙返回json字符串
+ */
+data class WiFiBleListBean(var wifi: MutableList)
diff --git a/app/src/main/java/com/abbidot/tracker/bean/WiFiZoneBean.kt b/app/src/main/java/com/abbidot/tracker/bean/WiFiZoneBean.kt
new file mode 100644
index 0000000..3d9f238
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/WiFiZoneBean.kt
@@ -0,0 +1,24 @@
+package com.abbidot.tracker.bean
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ *Created by .yzq on 2024/6/4/004.
+ * @link
+ * @description:
+ */
+@Parcelize
+data class WiFiZoneBean(
+ var wifiZoneId: String,
+ var deviceId: String,
+ var wifiZoneName: String,
+ var address: String,
+ var wifiMac: String,
+ var wifiName: String,
+ var longitude: Double,
+ var latitude: Double,
+ var type: Int //1是home 2是office
+) : Parcelable {
+ constructor() : this("", "", "", "", "", "", 0.0, 0.0, 1)
+}
diff --git a/app/src/main/java/com/abbidot/tracker/bean/WiFiZoneListBean.kt b/app/src/main/java/com/abbidot/tracker/bean/WiFiZoneListBean.kt
new file mode 100644
index 0000000..5c619f0
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/bean/WiFiZoneListBean.kt
@@ -0,0 +1,10 @@
+package com.abbidot.tracker.bean
+
+/**
+ *Created by .yzq on 2024/6/5/005.
+ * @link
+ * @description:
+ */
+data class WiFiZoneListBean(
+ var latitude: Double, var longitude: Double, var list: MutableList?
+)
diff --git a/app/src/main/java/com/abbidot/tracker/constant/ConstantInt.kt b/app/src/main/java/com/abbidot/tracker/constant/ConstantInt.kt
new file mode 100644
index 0000000..ebdd91a
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/constant/ConstantInt.kt
@@ -0,0 +1,122 @@
+package com.abbidot.tracker.constant
+
+import android.annotation.SuppressLint
+import androidx.annotation.IntDef
+
+/**
+ *Created by .yzq on 2022/4/8/008.
+ * @link
+ * @description:int 常量
+ */
+@SuppressLint("UniqueConstants")
+@IntDef(
+ ConstantInt.Open,
+ ConstantInt.Close,
+ ConstantInt.BadZone,
+ ConstantInt.GoodZone,
+ ConstantInt.LowBattery20,
+ ConstantInt.LowBattery10,
+ ConstantInt.LowBattery30,
+ ConstantInt.NoSignal,
+ ConstantInt.Line,
+ ConstantInt.Point,
+ ConstantInt.CircleShapeType,
+ ConstantInt.RectangleShapeType,
+ ConstantInt.UserLocationType,
+ ConstantInt.PolygonShapeType,
+ ConstantInt.OtherLocationType,
+ ConstantInt.SafeZone,
+ ConstantInt.NoGoZone,
+ ConstantInt.OtherPetType,
+ ConstantInt.DogPetType,
+ ConstantInt.CatPetType,
+ ConstantInt.WoMan,
+ ConstantInt.Man,
+ ConstantInt.Type0,
+ ConstantInt.Type1,
+ ConstantInt.Type2,
+ ConstantInt.Type3,
+ ConstantInt.Type4,
+ ConstantInt.SpecialType,
+ ConstantInt.isBind,
+ ConstantInt.NoBind,
+ ConstantInt.WeakSignal,
+ ConstantInt.DefaultSportGoal,
+ ConstantInt.MaxType,
+ ConstantInt.MinType,
+ ConstantInt.HeightType,
+ ConstantInt.WeightType,
+ ConstantInt.BasicPackage,
+ ConstantInt.PremiumPackage,
+ ConstantInt.MinSportGoal,
+ ConstantInt.NoShare,
+ ConstantInt.ReportTimeOutTime,
+ ConstantInt.PetLocationType
+)
+@Retention(AnnotationRetention.RUNTIME)
+annotation class ConstantInt {
+ companion object {
+ const val SpecialType = -1
+ const val Type0 = 0
+ const val Type1 = 1
+ const val Type2 = 2
+ const val Type3 = 3
+ const val Type4 = 4
+
+ const val OtherPetType = 0
+ const val DogPetType = 1
+ const val CatPetType = 2
+
+ const val MaxType = 0
+ const val MinType = 1
+ const val HeightType = 0
+ const val WeightType = 1
+
+ const val WoMan = 0
+ const val Man = 1
+
+ const val isBind = 1
+ const val NoBind = 0
+
+ const val Open = 1
+ const val Close = 0
+ const val BadZone = 1
+ const val GoodZone = 0
+ const val SafeZone = 1
+ const val NoGoZone = 2
+ const val LowBattery20 = 20
+ const val LowBattery10 = 10
+ const val LowBattery30 = 30
+ const val NoSignal = 0
+ const val WeakSignal = 50
+ const val Line = 2
+ const val Point = 3
+
+ //围栏样式 1=圆形,2=矩形,3=六边形
+ const val CircleShapeType = 1
+ const val RectangleShapeType = 2
+ const val PolygonShapeType = 3
+
+ const val OtherLocationType = 2
+ const val UserLocationType = 1
+ const val PetLocationType = 0
+
+ //默认的运动目标时间(min)
+ const val DefaultSportGoal = 60
+
+ //推荐最小的运动目标时间(min)
+ const val MinSportGoal = 30
+
+ //基础套餐
+ const val BasicPackage = 1
+
+ //高级套餐
+ const val PremiumPackage = 2
+
+ //不是分享的
+ const val NoShare = 0
+
+ //上报超时时间(min)
+ const val ReportTimeOutTime = 70
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/constant/ConstantString.kt b/app/src/main/java/com/abbidot/tracker/constant/ConstantString.kt
new file mode 100644
index 0000000..5a6153e
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/constant/ConstantString.kt
@@ -0,0 +1,118 @@
+package com.abbidot.tracker.constant
+
+import androidx.annotation.StringDef
+
+/**
+ *Created by .yzq on 2022/4/8/008.
+ * @link
+ * @description:String 常量
+ */
+@StringDef(
+ ConstantString.isCheck,
+ ConstantString.Amount,
+ ConstantString.Card,
+ ConstantString.Title,
+ ConstantString.Url,
+ ConstantString.MapDeviceBean,
+ ConstantString.Type,
+ ConstantString.DeviceAuthorized,
+ ConstantString.PetAuthorized,
+ ConstantString.DeviceId,
+ ConstantString.DeviceOutId,
+ ConstantString.FenceId,
+ ConstantString.Fence,
+ ConstantString.CurrentFence,
+ ConstantString.Edit,
+ ConstantString.PetLabels,
+ ConstantString.Pet,
+ ConstantString.PetHeight,
+ ConstantString.Man,
+ ConstantString.WoMan,
+ ConstantString.PetId,
+ ConstantString.PetHeadUrl,
+ ConstantString.DeviceInfo,
+ ConstantString.RechargeDevice,
+ ConstantString.SetMeal,
+ ConstantString.HistoryDataBean,
+ ConstantString.Mac,
+ ConstantString.TodayActiveTime,
+ ConstantString.Index,
+ ConstantString.Photo,
+ ConstantString.OrderId,
+ ConstantString.LkSetMeal,
+ ConstantString.PartnerCode,
+ ConstantString.JumpActivity,
+ ConstantString.WiFi,
+ ConstantString.WiFiZone,
+ ConstantString.Latitude,
+ ConstantString.Longitude,
+ ConstantString.UserBean,
+ ConstantString.BleDevice,
+ ConstantString.isFirstBind,
+ ConstantString.RechargeType,
+ ConstantString.Id,
+ ConstantString.PetWeight,
+ ConstantString.Upgrade,
+ ConstantString.PackageUnitMonth,
+ ConstantString.PackageUnitYear,
+ ConstantString.SetMealIndex
+)
+@Retention(AnnotationRetention.SOURCE)
+annotation class ConstantString {
+ companion object {
+
+ const val DeviceAuthorized = "isDeviceAuthorized"
+ const val PetAuthorized = "isPetAuthorized"
+ const val DeviceId = "deviceId"
+ const val DeviceOutId = "deviceOutId"
+ const val Mac = "mac"
+ const val FenceId = "fenceId"
+ const val Fence = "fence"
+ const val WiFi = "wifi"
+ const val WiFiZone = "wifiZone"
+ const val CurrentFence = "currentFence"
+ const val Edit = "isEdit"
+ const val PetLabels = "petLabels"
+ const val Pet = "pet"
+ const val PetHeadUrl = "petHeadUrl"
+ const val PetId = "petId"
+ const val PetHeight = "petHeight"
+ const val PetWeight = "petWeight"
+ const val TodayActiveTime = "todayActiveTime"
+ const val Man = "1"
+ const val WoMan = "0"
+ const val DeviceInfo = "deviceInfo"
+ const val BleDevice = "bleDevice"
+ const val RechargeDevice = "rechargeDevice"
+ const val RechargeType = "rechargeType"
+ const val PartnerCode = "partnerCode"
+ const val SetMeal = "setMeal"
+ const val SetMealIndex = "setMealIndex"
+ const val LkSetMeal = "LksetMeal"
+ const val JumpActivity = "jumpActivity"
+ const val Latitude = "latitude"
+ const val Longitude = "longitude"
+ const val isFirstBind = "isFirstBind"
+
+ const val isCheck = "isCheck"
+ const val Amount = "amount"
+ const val Card = "card"
+ const val Title = "title"
+ const val Id = "id"
+ const val Url = "url"
+ const val OrderId = "orderId"
+ const val MapDeviceBean = "mapDeviceBean"
+ const val UserBean = "userBean"
+ const val HistoryDataBean = "historyDataBean"
+ const val Upgrade = "upgrade"
+
+ //套餐单位
+ const val PackageUnitMonth = "MONTH"
+ const val PackageUnitYear = "YEAR"
+
+ //只是用来区分类型
+ const val Type = "type"
+ const val Photo = "photo"
+ const val Index = "index"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/constant/GetResultCallback.kt b/app/src/main/java/com/abbidot/tracker/constant/GetResultCallback.kt
new file mode 100644
index 0000000..43ec746
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/constant/GetResultCallback.kt
@@ -0,0 +1,13 @@
+package com.abbidot.tracker.constant
+
+/**
+ *Created by .yzq on 2022/2/7/007.
+ * @link
+ * @description:
+ */
+interface GetResultCallback {
+ fun onResult(any: Any)
+
+ //默认可以不重写,相当于java中的default修饰的
+ fun onRequestError(exceptionCode:String?) {}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/constant/KeyNames.kt b/app/src/main/java/com/abbidot/tracker/constant/KeyNames.kt
new file mode 100644
index 0000000..3ce9de2
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/constant/KeyNames.kt
@@ -0,0 +1,17 @@
+package com.abbidot.tracker.constant
+
+/**
+ *Created by .yzq on 2023/7/13/013.
+ * @link
+ * @description:
+ */
+class KeyNames {
+ companion object {
+ private const val COMMON_PREFIX = "com.abbidot.metadata"
+ const val BUG_LY_KEY_NAME = "$COMMON_PREFIX.bugly.key"
+ const val MAPBOX_ACCESS_TOKEN = "$COMMON_PREFIX.mapbox.access.token"
+ const val HTTP_REQUEST_KEY = "$COMMON_PREFIX.http.request.key"
+ const val STRIPE_RELEASE_KEY = "$COMMON_PREFIX.stripe.release.key"
+ const val STRIPE_TEST_KEY = "$COMMON_PREFIX.stripe.test.key"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/constant/MultipleEntity.kt b/app/src/main/java/com/abbidot/tracker/constant/MultipleEntity.kt
new file mode 100644
index 0000000..9dae90a
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/constant/MultipleEntity.kt
@@ -0,0 +1,23 @@
+package com.abbidot.tracker.constant
+
+import androidx.annotation.IntDef
+
+/**
+ *Created by .yzq on 2021/12/20/020.
+ * @link
+ * @description:多布局类型
+ */
+@IntDef(MultipleEntity.IMG, MultipleEntity.TEXT, MultipleEntity.IMG_TEXT, MultipleEntity.IMG_IMG,
+ MultipleEntity.IMG_TEXT_IMG, MultipleEntity.TEXT_TEXT_IMG, MultipleEntity.TEXT_NAME)
+@Retention(AnnotationRetention.SOURCE)
+annotation class MultipleEntity {
+ companion object {
+ const val TEXT = 0
+ const val IMG = 1
+ const val IMG_TEXT = 2
+ const val IMG_IMG = 3
+ const val IMG_TEXT_IMG = 4
+ const val TEXT_TEXT_IMG = 5
+ const val TEXT_NAME = 6
+ }
+}
diff --git a/app/src/main/java/com/abbidot/tracker/database/MyDatabase.kt b/app/src/main/java/com/abbidot/tracker/database/MyDatabase.kt
new file mode 100644
index 0000000..660139e
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/database/MyDatabase.kt
@@ -0,0 +1,68 @@
+package com.abbidot.tracker.database
+
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import com.abbidot.tracker.MyApplication
+import com.abbidot.tracker.bean.CreditCardBean
+import com.abbidot.tracker.bean.DeviceBean
+import com.abbidot.tracker.bean.MessageBean
+import com.abbidot.tracker.database.dao.CreditCardDao
+import com.abbidot.tracker.database.dao.DeviceDao
+import com.abbidot.tracker.database.dao.MessageDao
+
+/**
+ *Created by .yzq on 2021/11/6/006.
+ * @link
+ * @description:RoomDatabase实例
+ */
+//exportSchema = false,防止改数据库内容版本自动增加
+@Database(
+ entities = [DeviceBean::class, CreditCardBean::class, MessageBean::class],
+ version = 4,
+// autoMigrations = [AutoMigration(from = 1, to = 2)],
+ exportSchema = false,
+)
+abstract class MyDatabase : RoomDatabase() {
+ abstract fun deviceDao(): DeviceDao
+ abstract fun creditCardDao(): CreditCardDao
+ abstract fun messageDao(): MessageDao
+
+ companion object {
+
+ //https://blog.csdn.net/shulianghan/article/details/131040728
+// val MIGRATION_1_2 = object : Migration(1, 2) {
+// override fun migrate(database: SupportSQLiteDatabase) {
+// // 执行从旧版本升级到新版本的 SQL 语句
+//// database.execSQL("ALTER TABLE $DeviceTableName ADD COLUMN new_column INTEGER DEFAULT 0 NOT NULL")
+//// database.execSQL("ALTER TABLE $CreditCardTableName ADD COLUMN new_column INTEGER DEFAULT 0 NOT NULL")
+// database.execSQL("CREATE TABLE $MessageTableName(messageId TEXT NOT NULL PRIMARY KEY,title TEXT,message TEXT,sendTime TEXT,messageType INTEGER,imgUrl TEXT,isRead BIT)")
+// }
+// }
+
+ //MyDatabase单例模式
+ private val db: MyDatabase by lazy {
+ Room.databaseBuilder(MyApplication.instance, MyDatabase::class.java, "tracker_dp")
+// .addMigrations(MIGRATION_1_2)
+ .fallbackToDestructiveMigration()//删除旧表格并创建新表格,的方式升级数据库版本
+ .build()
+ }
+
+ //表名
+ const val CreditCardTableName = "creditCard"
+ const val DeviceTableName = "device"
+ const val MessageTableName = "message"
+
+ fun deviceDao(): DeviceDao {
+ return db.deviceDao()
+ }
+
+ fun creditCardDao(): CreditCardDao {
+ return db.creditCardDao()
+ }
+
+ fun messageDao(): MessageDao {
+ return db.messageDao()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/database/dao/BaseDao.kt b/app/src/main/java/com/abbidot/tracker/database/dao/BaseDao.kt
new file mode 100644
index 0000000..b134263
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/database/dao/BaseDao.kt
@@ -0,0 +1,119 @@
+package com.abbidot.tracker.database.dao
+
+import android.util.Log
+import androidx.room.*
+import androidx.sqlite.db.SimpleSQLiteQuery
+import androidx.sqlite.db.SupportSQLiteQuery
+
+/**
+ *Created by .yzq on 2022/4/1/001.
+ * @link
+ * @description:数据库Dao基类
+ */
+interface BaseDao {
+ /**
+ * 获取表名
+ */
+// val tableName: String
+// get() {
+// val clazz =
+// (javaClass.superclass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<*>
+// val tableName = clazz.simpleName
+// LogUtil.d("ez", "getTableName: -->$tableName")
+// return tableName
+// }
+
+ /**
+ * 添加单个对象
+ * OnConflictStrategy.REPLACE新数据替换旧数据
+ */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insert(obj: T): Long
+
+ /**
+ * 添加数组对象数据
+ */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insert(vararg objs: T): LongArray?
+
+ /**
+ * 添加对象集合
+ */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insert(personList: List): List
+
+ /**
+ * 根据对象中的主键删除(主键是自动增长的,无需手动赋值)
+ */
+ @Delete
+ fun delete(obj: T)
+
+ /**
+ * 根据对象中的主键更新(主键是自动增长的,无需手动赋值)
+ */
+ @Update
+ fun update(vararg obj: T): Int
+
+ fun deleteAll(tableName:String): Int {
+ val query = SimpleSQLiteQuery("delete from $tableName")
+ return doDeleteAll(query)
+ }
+
+ fun findAll(tableName:String): List? {
+ val query = SimpleSQLiteQuery("select * from $tableName")
+ return doFindAll(query)
+ }
+
+ fun find(id: Long,tableName:String): T? {
+ val query = SimpleSQLiteQuery("select * from $tableName where id = ?", arrayOf(id))
+ return doFind(query)
+ }
+
+ /**
+ * [params] 列名
+ * [value] 列的值
+ */
+ fun deleteByParams(params: String, value: String,tableName:String): Int {
+ val query = SimpleSQLiteQuery("delete from $tableName where $params='${value}'")
+ Log.d("ez", "deleteByParams: ${"delete from $tableName where $params='${value}'"}")
+ return doDeleteByParams(query)
+ }
+
+ /**
+ * 分页查询,支持传入多个字段,但必须要按照顺序传入
+ * key = value,key = value 的形式,一一对应(可以使用 stringbuilder 去构造一下,这里就不演示了)
+ */
+ fun doQueryByLimit(tableName:String,vararg string: String, limit: Int = 10, offset: Int = 0): List? {
+ val query = SimpleSQLiteQuery(
+ "SELECT * FROM $tableName WHERE ${string[0]} = '${string[1]}' limit $limit offset $offset")
+ return doQueryByLimit(query)
+ }
+
+ /**
+ * 降序分页查询
+ */
+ fun doQueryByOrder(tableName:String,vararg string: String, limit: Int = 10, offset: Int = 10): List? {
+ val query = SimpleSQLiteQuery(
+ "SELECT * FROM $tableName ORDER BY ${string[0]} desc limit '${limit}' offset '${offset}'")
+ return doQueryByOrder(query)
+ }
+
+
+ @RawQuery
+ fun doFindAll(query: SupportSQLiteQuery): List?
+
+ @RawQuery
+ fun doFind(query: SupportSQLiteQuery): T
+
+ @RawQuery
+ fun doDeleteAll(query: SupportSQLiteQuery): Int
+
+ @RawQuery
+ fun doDeleteByParams(query: SupportSQLiteQuery): Int
+
+ @RawQuery
+ fun doQueryByLimit(query: SupportSQLiteQuery): List?
+
+ @RawQuery
+ fun doQueryByOrder(query: SupportSQLiteQuery): List?
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/database/dao/CreditCardDao.kt b/app/src/main/java/com/abbidot/tracker/database/dao/CreditCardDao.kt
new file mode 100644
index 0000000..03131aa
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/database/dao/CreditCardDao.kt
@@ -0,0 +1,12 @@
+package com.abbidot.tracker.database.dao
+
+import androidx.room.Dao
+import com.abbidot.tracker.bean.CreditCardBean
+
+/**
+ *Created by .yzq on 2022/4/1/001.
+ * @link
+ * @description:
+ */
+@Dao
+interface CreditCardDao : BaseDao
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/database/dao/DeviceDao.kt b/app/src/main/java/com/abbidot/tracker/database/dao/DeviceDao.kt
new file mode 100644
index 0000000..ff09513
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/database/dao/DeviceDao.kt
@@ -0,0 +1,18 @@
+package com.abbidot.tracker.database.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import com.abbidot.tracker.bean.DeviceBean
+import com.abbidot.tracker.database.MyDatabase
+
+/**
+ *Created by .yzq on 2021/11/8/008.
+ * @link
+ * @description:DeviceBean表的dao
+ */
+@Dao
+interface DeviceDao : BaseDao {
+
+ @Query("SELECT * FROM ${MyDatabase.DeviceTableName} WHERE macId LIKE :mac LIMIT 1")
+ fun findByMac(mac: String): DeviceBean?
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/database/dao/MessageDao.kt b/app/src/main/java/com/abbidot/tracker/database/dao/MessageDao.kt
new file mode 100644
index 0000000..ac8bfc5
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/database/dao/MessageDao.kt
@@ -0,0 +1,12 @@
+package com.abbidot.tracker.database.dao
+
+import androidx.room.Dao
+import com.abbidot.tracker.bean.MessageBean
+
+/**
+ *Created by .yzq on 2024/7/19/019.
+ * @link
+ * @description:
+ */
+@Dao
+interface MessageDao : BaseDao
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/adapter/RechargeAmountCNAdapter.kt b/app/src/main/java/com/abbidot/tracker/deprecated/adapter/RechargeAmountCNAdapter.kt
new file mode 100644
index 0000000..5d21f27
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/adapter/RechargeAmountCNAdapter.kt
@@ -0,0 +1,62 @@
+package com.abbidot.tracker.deprecated.adapter
+
+import android.content.Context
+import android.view.View
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.SetMealBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.util.ViewUtil
+
+/**
+ *Created by .yzq on 2022/7/23/023.
+ * @link
+ * @description:
+ */
+class RechargeAmountCNAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+
+ private var mSelectIndex = -1
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_recharge_amount_cn
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: SetMealBean) {
+ val view = holder!!.itemView
+ if (position == mSelectIndex) {
+ view.background = ContextCompat.getDrawable(mContext, R.drawable.shape10_yellow_bg)
+ } else {
+ view.background = ContextCompat.getDrawable(mContext, R.drawable.shape12_gray_white_bg)
+ }
+ ViewUtil.instance.setShapeRadius(view, 6)
+
+ if (item.hotType == ConstantInt.Type1) {
+ holder.getImageView(R.id.recharge_amount_cn_normal_hot_image).visibility = View.VISIBLE
+ } else {
+ holder.getImageView(R.id.recharge_amount_cn_normal_hot_image).visibility = View.GONE
+ }
+ val period = item.period
+ val perMonth = if (period < 2) {
+ String.format(mContext.getString(R.string.pet_managet_age), period)
+ } else {
+ String.format(mContext.getString(R.string.pet_managet_age), period)
+ }
+ holder.setText(R.id.recharge_amount_cn_two_time, perMonth)
+ holder.setText(R.id.recharge_amount_cn_two_money, item.accountFee.toString())
+
+ val averageMonth = Utils.formatDecimal(item.accountFee / (12 * period), 2)
+ val monthString = String.format(mContext.getString(R.string.txt_perMonth), averageMonth)
+ holder.setText(R.id.recharge_amount_cn_two_description, monthString)
+ }
+
+ fun setSelectIndex(index: Int) {
+ mSelectIndex = index
+ notifyDataSetChanged()
+ }
+
+ fun getSelectIndex() = mSelectIndex
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/adapter/RechargeHistoryCNAdapter.kt b/app/src/main/java/com/abbidot/tracker/deprecated/adapter/RechargeHistoryCNAdapter.kt
new file mode 100644
index 0000000..9c111f5
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/adapter/RechargeHistoryCNAdapter.kt
@@ -0,0 +1,31 @@
+package com.abbidot.tracker.deprecated.adapter
+
+import android.content.Context
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.RechargeHistoryBean
+
+/**
+ *Created by .yzq on 2022/1/29/029.
+ * @link
+ * @description:充值记录适配器
+ */
+class RechargeHistoryCNAdapter(ctx: Context, list: MutableList?) :
+ BaseRecyclerAdapter(ctx, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_recharge_history_cn
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: RechargeHistoryBean) {
+ holder!!.setText(R.id.recharge_history_cn_pay_time, item.payTime)
+ val totalString = String.format(mContext.getString(R.string.txt_total_money),
+ "+${mContext.getString(R.string.txt_month_until)}${item.cost}")
+ holder.setText(R.id.recharge_history_cn_pay_money, totalString)
+ holder.setText(R.id.recharge_history_cn_meal_name, item.feePackage)
+ val deviceName = String.format(mContext.getString(R.string.txt_tracker_name),
+ item.deviceOutId)
+ holder.setText(R.id.recharge_history_cn_device_name, deviceName)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/adapter/SelectPaymentMethodAdapter.kt b/app/src/main/java/com/abbidot/tracker/deprecated/adapter/SelectPaymentMethodAdapter.kt
new file mode 100644
index 0000000..4b852b4
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/adapter/SelectPaymentMethodAdapter.kt
@@ -0,0 +1,51 @@
+package com.abbidot.tracker.deprecated.adapter
+
+import android.content.Context
+import androidx.appcompat.widget.AppCompatCheckedTextView
+import androidx.core.content.ContextCompat
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.tracker.R
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.util.ViewUtil
+
+
+/**
+ *Created by .yzq on 2022/3/29/029.
+ * @link
+ * @description:
+ */
+class SelectPaymentMethodAdapter(
+ ctx: Context, list: MutableList?, showPaypal: Boolean = true
+) : BaseRecyclerAdapter(ctx, list) {
+
+ private val mShowPaypal = showPaypal
+
+ override fun getEmptyLayoutId(viewType: Int) = 0
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.item_payment_method_layout
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: MenuTxtBean) {
+ ViewUtil.instance.setShapeRadius(holder!!.itemView, 6)
+ val textView = holder.getTextView(R.id.item_payment_method_text_view)
+ textView.setCompoundDrawablesWithIntrinsicBounds(
+ item.imageId, 0, 0, 0
+ )
+ (holder.getView(R.id.item_payment_method_checkbox) as AppCompatCheckedTextView).isChecked =
+ item.isSwitch
+
+ if (mShowPaypal && (position == 0 || position == getData().size - 1)) {
+ textView.text = item.menuName
+ } else if (position == getData().size - 1) {
+ textView.text = item.menuName
+ } else {
+ val str = item.menuName
+ var cardFormat = str.substring(0, 4)
+ for (i in 0 until str.length - 8) {
+ cardFormat = "$cardFormat*"
+ }
+ cardFormat += str.substring(str.length - 4, str.length)
+ textView.text = cardFormat
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/DetailActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/DetailActivity.kt
new file mode 100644
index 0000000..787db4b
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/DetailActivity.kt
@@ -0,0 +1,99 @@
+package com.abbidot.tracker.deprecated.ui.activity
+
+import android.widget.Toast
+import androidx.recyclerview.widget.DiffUtil
+import com.abbidot.baselibrary.constant.EventName
+import com.abbidot.baselibrary.eventbus.XEventBus
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.list.RecyclerViewHolder
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.base.BaseDiffCallBack
+import com.abbidot.tracker.bean.DeviceBean
+import com.abbidot.tracker.databinding.ActivityDetailBinding
+import com.abbidot.tracker.dialog.DialogUtils
+import com.abbidot.tracker.util.ViewUtil
+import com.qmuiteam.qmui.util.QMUIStatusBarHelper
+import com.qmuiteam.qmui.widget.dialog.QMUITipDialog
+
+class DetailActivity : BaseActivity(ActivityDetailBinding::inflate) {
+
+ private lateinit var mAdapter: BaseRecyclerAdapter
+ private lateinit var list: MutableList
+
+ override fun getTopBar() = mViewBinding.titleGg.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ //设置状态栏黑色字体与图标
+ QMUIStatusBarHelper.setStatusBarLightMode(this)
+ XEventBus.post(EventName.Test, "cccccccccccccccccccc")
+
+ setTopBarTitle(R.string.app_name)
+
+// list = mutableListOf(
+// DeviceBean(5, 4, "tesdfd", conState = ConState.CONNECTED, "7547sgdgdgy64e4r"),
+// DeviceBean(3, 2, "65757", conState = ConState.DISCONNECTED, "gujghj"))
+
+ mAdapter = object : BaseRecyclerAdapter(this, list) {
+ override fun getEmptyLayoutId(viewType: Int)=R.layout.layout_empty_view
+
+ override fun getItemLayoutId(viewType: Int) = R.layout.layout_list_item
+
+ override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DeviceBean) {
+ holder!!.setText(R.id.sdagfdsgg, item.deviceName)
+ }
+ }
+
+ ViewUtil.instance.setRecyclerViewVerticalLinearLayout(mContext,mViewBinding.recyclerView, mAdapter)
+
+ Toast.makeText(application, AppUtils.isDebug().toString(), Toast.LENGTH_LONG).show()
+
+// val newList: MutableList = ArrayList()
+ mViewBinding.btnTest.setOnClickListener {
+ val newList: MutableList = ArrayList()
+ list = mAdapter.getData()
+ for (i in 0 until list.size) {
+ newList.add(list[i].copy())
+ }
+
+// newList.add(DeviceBean(list.size, 4, Math.random().toString(),
+// conState = ConState.CONNECTED, "7547sgdgdgy64e4r"))
+ onRefreshData(newList)
+
+ showToast("add")
+ }
+
+ mViewBinding.testRemove.setOnClickListener {
+ val newList: MutableList = ArrayList()
+ list = mAdapter.getData()
+ for (i in 0 until list.size) {
+ newList.add(list[i].copy())
+ }
+ newList.removeAt(2)
+ onRefreshData(newList)
+ DialogUtils.showTipDialog(mActivity!!, mViewBinding.testRemove, "remove succes",
+ QMUITipDialog.Builder.ICON_TYPE_SUCCESS)
+ }
+ }
+
+ private fun onRefreshData(newList: MutableList) {
+ mAdapter.setData(newList)
+
+
+ val diffResult =
+ DiffUtil.calculateDiff(object : BaseDiffCallBack(list, newList) {
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
+ list[oldItemPosition].deviceId == newList[newItemPosition].deviceId
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
+ list[oldItemPosition].deviceName == newList[newItemPosition].deviceName
+
+ }, true)
+
+
+ diffResult.dispatchUpdatesTo(mAdapter)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/LoginRegisterCNActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/LoginRegisterCNActivity.kt
new file mode 100644
index 0000000..0c93b1a
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/LoginRegisterCNActivity.kt
@@ -0,0 +1,126 @@
+package com.abbidot.tracker.deprecated.ui.activity
+
+import androidx.appcompat.widget.AppCompatCheckBox
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.commit
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.databinding.ActivityLoginRegisterCnBinding
+import com.abbidot.tracker.deprecated.ui.fragment.forgot.ForgetPasswordCNFinishFragment
+import com.abbidot.tracker.deprecated.ui.fragment.forgot.ForgetPasswordCNStartFragment
+import com.abbidot.tracker.deprecated.ui.fragment.login.BindPhoneCNFragment
+import com.abbidot.tracker.deprecated.ui.fragment.login.LoginCNAccountFragment
+import com.abbidot.tracker.deprecated.ui.fragment.login.LoginCNCodeFragment
+import com.abbidot.tracker.deprecated.ui.fragment.login.LoginCNFirstFragment
+import com.abbidot.tracker.deprecated.ui.fragment.register.RegisterCNFinishFragment
+import com.abbidot.tracker.deprecated.ui.fragment.register.RegisterCNStartFragment
+
+/**
+ * 国内登录界面
+ */
+class LoginRegisterCNActivity :
+ BaseActivity(ActivityLoginRegisterCnBinding::inflate) {
+
+ var mWXId = ""
+ var mPhone = ""
+
+ //区分忘记密码 和找回密码
+ var mType = ConstantInt.Close
+
+ companion object {
+ const val Fragment_First = 0
+ const val Fragment_Account_Login = 1
+ const val Fragment_Code_Login = 2
+ const val Fragment_Register_Start = 3
+ const val Fragment_Register_Finish = 4
+ const val Fragment_Bind_Phone = 5
+ const val Fragment_Forget_Password_Start = 6
+ const val Fragment_Forget_Password_Finish = 7
+ }
+
+
+ private lateinit var mFragmentList: MutableList
+
+ override fun getTopBar() = mViewBinding.loginCnTopBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTranslucentTopBar()
+ mViewBinding.loginCnTopBar.titleTopBarLayout.setBackgroundResource(R.color.btn_yellow_color)
+
+ mFragmentList = mutableListOf(
+ LoginCNFirstFragment.newInstance(mContext),
+ LoginCNAccountFragment.newInstance(mContext),
+ LoginCNCodeFragment.newInstance(mContext),
+ RegisterCNStartFragment.newInstance(mContext),
+ RegisterCNFinishFragment.newInstance(mContext),
+ BindPhoneCNFragment.newInstance(mContext),
+ ForgetPasswordCNStartFragment.newInstance(mContext),
+ ForgetPasswordCNFinishFragment.newInstance(mContext)
+ )
+
+ var index = 0
+ intent.extras?.let {
+ index = it.getInt(ConstantString.Index, Fragment_First)
+ mType = it.getInt(ConstantString.Type, ConstantInt.Close)
+ }
+ switchFragment(index)
+ }
+
+ fun switchFragment(index: Int) {
+
+ setTopTitle(getString(R.string.login_txt_welcome))
+ setTopContent(getString(R.string.login_txt_seeyou))
+
+ supportFragmentManager.commit {
+
+ hideFragment(this, mFragmentList[Fragment_First])
+ hideFragment(this, mFragmentList[Fragment_Account_Login])
+ hideFragment(this, mFragmentList[Fragment_Code_Login])
+ hideFragment(this, mFragmentList[Fragment_Register_Start])
+ hideFragment(this, mFragmentList[Fragment_Register_Finish])
+ hideFragment(this, mFragmentList[Fragment_Bind_Phone])
+ hideFragment(this, mFragmentList[Fragment_Forget_Password_Start])
+ hideFragment(this, mFragmentList[Fragment_Forget_Password_Finish])
+
+ //为FragmentTransaction添加指定的自定义属性动画
+ setCustomAnimations(
+ R.anim.slide_in_right,
+ R.anim.slide_out_left,
+ R.anim.slide_still,
+ R.anim.slide_out_right
+ )
+
+ if (mFragmentList[index].isAdded) {
+ show(mFragmentList[index])
+ } else {
+ add(R.id.login_cn_steps_frame, mFragmentList[index])
+ }
+ }
+ }
+
+ fun setTopTitle(title: String) {
+ mViewBinding.loginCnTopTitle.text = title
+ }
+
+ fun setTopContent(content: String) {
+ mViewBinding.loginCnTopContent.text = content
+ }
+
+ /**
+ * 是否同意协议
+ */
+ fun isAgreePolicy(checkBox: AppCompatCheckBox): Boolean {
+ if (!checkBox.isChecked) {
+ val tips = getString(R.string.register_txt_agree1) + getString(
+ R.string.register_txt_policy
+ ) + getString(R.string.register_txt_agree2) + getString(
+ R.string.register_txt_terms
+ )
+ showToast(tips)
+ }
+ return checkBox.isChecked
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/SwipeActionActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/SwipeActionActivity.kt
new file mode 100644
index 0000000..653a3e4
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/SwipeActionActivity.kt
@@ -0,0 +1,158 @@
+package com.abbidot.tracker.deprecated.ui.activity
+
+import android.graphics.Color
+import android.widget.TextView
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.RecyclerView
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.base.BaseDiffCallBack
+import com.abbidot.tracker.base.BaseQMUIRVItemSwipeAction
+import com.abbidot.tracker.base.BaseSwipeMenuAdapter
+import com.abbidot.tracker.databinding.ActivitySwipeActionBinding
+import com.abbidot.tracker.util.ViewUtil
+import com.qmuiteam.qmui.recyclerView.QMUIRVItemSwipeAction
+import com.qmuiteam.qmui.recyclerView.QMUISwipeAction
+import com.qmuiteam.qmui.recyclerView.QMUISwipeViewHolder
+import com.qmuiteam.qmui.widget.pullRefreshLayout.QMUIPullRefreshLayout
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class SwipeActionActivity :
+ BaseActivity(ActivitySwipeActionBinding::inflate) {
+
+ private lateinit var mAdapter: BaseSwipeMenuAdapter
+ private lateinit var list: MutableList
+
+ override fun getTopBar() = mViewBinding.swipeTestBar.titleTopBar
+
+ override fun initData() {
+ setTopBarTitle("滑动菜单")
+
+ list = mutableListOf()
+
+ initMenu()
+
+ ViewUtil.instance.setRecyclerViewDecorationLinearLayoutManager(mContext!!,
+ mViewBinding.swipeTestPull.pullRefreshRv,mAdapter)
+
+ mViewBinding.swipeTestPull.onlyPullToRefresh.setOnPullListener(object :
+ QMUIPullRefreshLayout.OnPullListener {
+ override fun onMoveTarget(offset: Int) {
+ }
+
+ override fun onMoveRefreshView(offset: Int) {
+ }
+
+ override fun onRefresh() {
+ mViewBinding.swipeTestPull.onlyPullToRefresh.postDelayed(Runnable {
+ list.clear()
+ onDataLoaded()
+ mViewBinding.swipeTestPull.onlyPullToRefresh.finishRefresh()
+ }, 1000)
+ }
+ })
+ mAdapter.setOnAgainClickListener(object : BaseRecyclerAdapter.OnAgainClickListener {
+ override fun onAgainListener() {
+ showLoading(true)
+ mViewBinding.swipeTestPull.pullRefreshRv.postDelayed(Runnable {
+ onDataLoaded()
+ showLoading(false)
+ }, 1500)
+ }
+ })
+
+// onDataLoaded()
+ }
+
+ private fun initMenu() {
+ val menu: MutableList = mutableListOf()
+ mAdapter = object : BaseSwipeMenuAdapter(mContext!!, list) {
+
+ override fun getEmptyLayoutId(viewType: Int) = R.layout.layout_empty_view
+ override fun getItemLayoutId(viewType: Int) = R.layout.layout_list_item
+
+ override fun getSwipeActions(): MutableList {
+ return menu
+ }
+
+ override fun bindData(holder: QMUISwipeViewHolder?, position: Int, item: String) {
+ holder!!.itemView.findViewById(R.id.sdagfdsgg).text = item
+ }
+
+ }
+ val deleteAction = mAdapter.mActionBuilder.text("删除").backgroundColor(Color.RED).build()
+ val writeReviewAction =
+ mAdapter.mActionBuilder.text("写想法").backgroundColor(Color.BLUE).build()
+ menu.add(deleteAction)
+// menu.add(writeReviewAction)
+
+ val itemSwipeAction = object : BaseQMUIRVItemSwipeAction(QMUIRVItemSwipeAction.SWIPE_LEFT) {
+ override fun removeItem(position: Int) {
+ val newList = mAdapter.remove(mAdapter.getData(), position)
+ updateAdapter(mAdapter.getData(), newList)
+ }
+
+ override fun onClickAction(swipeAction: QMUIRVItemSwipeAction?,
+ selected: RecyclerView.ViewHolder?,
+ action: QMUISwipeAction?) {
+ super.onClickAction(swipeAction, selected, action)
+ if (action == deleteAction) {
+ removeItem(selected!!.adapterPosition)
+ } else {
+ swipeAction!!.clear()
+ }
+ }
+ }
+ val swipeAction = QMUIRVItemSwipeAction(true, itemSwipeAction)
+ swipeAction.attachToRecyclerView(mViewBinding.swipeTestPull.pullRefreshRv)
+ }
+
+ private fun onDataLoaded() {
+ val data: MutableList = ArrayList(
+ listOf("Helps", "Maintain", "Liver", "Health", "Function", "Supports", "Healthy",
+ "Fat", "Metabolism", "Nuturally", "Bracket", "Refrigerator", "Bathtub",
+ "Wardrobe", "Comb", "Apron", "Carpet", "Bolster", "Pillow", "Cushion"))
+ data.shuffle()
+ list = mAdapter.getData()
+
+ updateAdapter(list, data)
+ }
+
+ private fun updateAdapter(oldList: MutableList, newList: MutableList) {
+ if (oldList.size == 0) {
+ mAdapter.setData(newList)
+ mAdapter.notifyDataSetChanged()
+ return
+ }
+ lifecycleScope.launch {
+ //异步新旧数据比较
+ withContext(Dispatchers.Default) {
+ useDiffUtil(oldList, newList)
+ }.dispatchUpdatesTo(mAdapter)
+
+ //刷新完成重新定位到第一个数据
+ mViewBinding.swipeTestPull.pullRefreshRv.scrollToPosition(0)
+ }
+
+ }
+
+ /**
+ * 数据比较
+ */
+ private fun useDiffUtil(oldList: MutableList,
+ newList: MutableList): DiffUtil.DiffResult {
+ mAdapter.setData(newList)
+ return DiffUtil.calculateDiff(object : BaseDiffCallBack(oldList, newList) {
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
+ oldList[oldItemPosition] == newList[newItemPosition]
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
+ oldList[oldItemPosition] == newList[newItemPosition]
+
+ }, true)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/data/HistoryDataActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/data/HistoryDataActivity.kt
new file mode 100644
index 0000000..0479edf
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/data/HistoryDataActivity.kt
@@ -0,0 +1,186 @@
+package com.abbidot.tracker.deprecated.ui.activity.data
+
+import android.text.TextUtils
+import android.view.View
+import androidx.activity.viewModels
+import androidx.fragment.app.commit
+import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.util.MMKVUtil
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.HistoryDataBean
+import com.abbidot.tracker.bean.PetBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.databinding.ActivityHistoryDataBinding
+import com.abbidot.tracker.ui.common.map.HistoryDataMapCommon
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.vm.DataDetailViewModel
+import com.abbidot.tracker.vm.GeoCoderViewModel
+import com.abbidot.tracker.widget.MapMarkerInfoView
+import com.abbidot.tracker.widget.VerticalTopToBottomSeekBar
+
+/**
+ * 历史数据
+ */
+class HistoryDataActivity :
+ BaseActivity(ActivityHistoryDataBinding::inflate) {
+
+ val mDataDetailViewModel: DataDetailViewModel by viewModels()
+ val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
+
+ //方便保存地理反编译信息
+ private lateinit var mHistoryDataList: MutableList
+
+ lateinit var mPet: PetBean
+
+ private lateinit var mHistoryDataMapCommon: HistoryDataMapCommon
+
+ override fun getTopBar() = mViewBinding.activeHistoryDataBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ //设置沉浸状态栏颜色
+ mViewBinding.activeHistoryDataBar.titleTopBarLayout.setBackgroundResource(
+ R.color.sleep_time_gray_color
+ )
+ setTopBarTitle(R.string.data_active_history)
+
+ mPet = Util.getParcelableAdaptive(intent, ConstantString.Pet, PetBean::class.java)!!
+ mHistoryDataList = mutableListOf()
+
+ mHistoryDataMapCommon = HistoryDataMapCommon()
+ val fragment = mHistoryDataMapCommon.getMapFragment(
+ this, MapMarkerInfoView(mContext), mGeoCoderViewModel
+ ) {}
+ supportFragmentManager.commit {
+ add(R.id.history_data_map_view, fragment)
+ }
+
+ val today = Utils.getCurrentTime(Utils.DATE_FORMAT_PATTERN_CN)
+ mViewBinding.historyDataHorizontalCalenderView.setOnDaySelectedListener { hasChanged, year, month, day, week, item ->
+ if (hasChanged) {
+ val date = if (item.isCurrent) {
+ today
+ } else {
+ mViewBinding.historyDataHorizontalCalenderView.fillingDate(
+ "-", year, month, day
+ )
+ }
+ mViewBinding.historyDataDate.text = date
+ initState()
+ mDataDetailViewModel.getHistoryByDay(this, mPet.deviceId, 1, 1)
+ }
+ }
+
+ val type = MMKVUtil.getInt(MMKVKey.LineSelectPosition, ConstantInt.Line)
+ if (type == ConstantInt.Line) {
+ mViewBinding.historyDateMapLine.isChecked = true
+ } else {
+ mViewBinding.historyDateMapNumber.isChecked = true
+ }
+
+ initEven()
+
+ initState()
+ }
+
+ override fun liveDataObserve() {
+ mDataDetailViewModel.mHistoryDetailLive.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+ setLatLngData(data)
+ }
+ })
+ }
+
+ //地理反编译成功返回
+ mGeoCoderViewModel.mLatLonAddressLiveData.observe(this) {
+ mViewBinding.historyDataAddress.apply {
+ visibility = if (TextUtils.isEmpty(it)) {
+ View.GONE
+ } else {
+ View.VISIBLE
+ }
+ text = it
+ mHistoryDataList[mViewBinding.seekMapLine.progress].address = it
+ }
+ }
+ }
+
+ private fun initEven() {
+ mViewBinding.seekMapLine.setOnSeekBarChangeProgressListener(object :
+ VerticalTopToBottomSeekBar.OnSeekBarChangeListener {
+ override fun onProgressChanged(progress: Int) {
+ mHistoryDataMapCommon.slideChanged(progress)
+ }
+
+ override fun onStopChanged(progress: Int) {
+ val historyDataBean = mHistoryDataList[progress]
+ showDate(historyDataBean.timeStamp * 1000)
+
+ val address = historyDataBean.address
+ if (TextUtils.isEmpty(address)) {
+ mHistoryDataMapCommon.slideStopChanged(progress)
+ } else {
+ mViewBinding.historyDataAddress.text = address
+ }
+ }
+ })
+
+ mViewBinding.historyDateMapTypeGroup.setOnCheckedChangeListener { _, checkedId ->
+ mViewBinding.seekMapLine.progress = mViewBinding.seekMapLine.max
+ when (checkedId) {
+ mViewBinding.historyDateMapLine.id -> {
+ MMKVUtil.putInt(MMKVKey.LineSelectPosition, ConstantInt.Line)
+ mHistoryDataMapCommon.addSetLine()
+ }
+
+ mViewBinding.historyDateMapNumber.id -> {
+ MMKVUtil.putInt(MMKVKey.LineSelectPosition, ConstantInt.Point)
+ mHistoryDataMapCommon.addSetNumber()
+ }
+ }
+ }
+ }
+
+ private fun initState() {
+ mViewBinding.apply {
+ historyDataAddress.visibility = View.GONE
+ historyDataDate.visibility = View.GONE
+ seekMapLine.progress = 0
+ }
+ mHistoryDataMapCommon.clearAllMarker()
+ setSeekBarMax(0)
+ }
+
+ private fun setLatLngData(data: MutableList) {
+ mHistoryDataList = data
+ if (data.size == 0) return
+
+ val max = data.size - 1
+ setSeekBarMax(max)
+ showDate(data[max].timeStamp * 1000)
+
+ mHistoryDataMapCommon.setLatLngData(data)
+ }
+
+ private fun showDate(time: Long) {
+ val date = Utils.formatTime(time, Utils.DATE_FORMAT_PATTERN_CN3)
+ mViewBinding.historyDataDate.apply {
+ visibility = View.VISIBLE
+ text = date
+ }
+ }
+
+ private fun setSeekBarMax(max: Int) {
+ mViewBinding.seekMapLine.let {
+ it.max = max
+ //定位中心显示最后一个经纬度
+ it.progress = max
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/map/HomeMapNavigationActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/map/HomeMapNavigationActivity.kt
new file mode 100644
index 0000000..6a45265
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/map/HomeMapNavigationActivity.kt
@@ -0,0 +1,234 @@
+package com.abbidot.tracker.deprecated.ui.activity.map
+
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
+import android.content.Intent
+import android.text.TextUtils
+import android.view.View
+import android.view.animation.AccelerateDecelerateInterpolator
+import android.view.animation.Animation
+import androidx.activity.viewModels
+import androidx.fragment.app.commit
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.util.AppUtils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.adapter.SelectMapListDialogAdapter
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.HistoryDataBean
+import com.abbidot.tracker.bean.MapDeviceBean
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.bean.PetBean
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.databinding.ActivityHomeMapNavigationBinding
+import com.abbidot.tracker.dialog.SelectMapListDialog
+import com.abbidot.tracker.ui.common.map.NavigationMapCommon
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.abbidot.tracker.vm.FencesMapViewModel
+import com.abbidot.tracker.vm.GeoCoderViewModel
+
+
+/**
+ * 首页跳转导航
+ */
+class HomeMapNavigationActivity :
+ BaseActivity(ActivityHomeMapNavigationBinding::inflate) {
+
+ val mFencesMapViewModel: FencesMapViewModel by viewModels()
+ private val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
+
+ private val mMapGooglePackageName = "com.google.android.apps.maps"
+ private val mMapGaoDePackageName = "com.autonavi.minimap"
+
+ private lateinit var mSelectMapListDialogAdapter: SelectMapListDialogAdapter
+ private var mSelectMapListDialog: SelectMapListDialog? = null
+ var mMapDeviceBean: MapDeviceBean? = null
+
+ private lateinit var mNavigationMapCommon: NavigationMapCommon
+
+ override fun getTopBar() = mViewBinding.homeMapNavigationBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ var historyDataBean: HistoryDataBean? = null
+ var pet: PetBean? = null
+ intent.extras?.apply {
+ pet = Util.getParcelableAdaptive(intent, ConstantString.Pet, PetBean::class.java)
+ historyDataBean = Util.getParcelableAdaptive(
+ intent, ConstantString.HistoryDataBean, HistoryDataBean::class.java
+ )
+ mMapDeviceBean = Util.getParcelableAdaptive(
+ intent, ConstantString.MapDeviceBean, MapDeviceBean::class.java
+ )
+ }
+ if (null == historyDataBean) historyDataBean = HistoryDataBean()
+ if (null == pet) pet = PetBean()
+ if (null == mMapDeviceBean) mMapDeviceBean = MapDeviceBean()
+//
+// val title = String.format(getString(R.string.map_navigate), pet!!.petName)
+// setTopBarTitle(title)
+
+ mNavigationMapCommon = NavigationMapCommon()
+ val fragment = mNavigationMapCommon.getMapFragment(mContext, pet!!.imgurl)
+ supportFragmentManager.commit {
+ add(R.id.home_map_navigation_map_view, fragment)
+ }
+
+ val mapList = mutableListOf()
+ ViewUtil.instance.addMenuBean(
+ mapList,
+ getString(R.string.map_navigate_map_google),
+ mMapGooglePackageName,
+ R.drawable.ico_map_google
+ )
+ ViewUtil.instance.addMenuBean(
+ mapList,
+ getString(R.string.map_navigate_map_gaode),
+ mMapGaoDePackageName,
+ R.drawable.ico_map_gaode
+ )
+
+ mSelectMapListDialogAdapter = SelectMapListDialogAdapter(mContext!!, mapList)
+ mSelectMapListDialogAdapter.setOnItemClickListener(object :
+ BaseRecyclerAdapter.OnItemClickListener {
+ override fun onItemClick(itemView: View?, pos: Int) {
+ selectMapNavigation(mapList[pos])
+ }
+ })
+
+ setOnClickListenerViews(mViewBinding.selectMapNavigationBtn)
+
+
+// val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build()
+// val mGoogleSignInClient: GoogleSignInClient = GoogleSignIn.getClient(this, gso)
+// val mGoogleApiClient = mGoogleSignInClient.asGoogleApiClient()
+
+
+ ViewUtil.instance.imageLoadUrl(
+ mViewBinding.homeMapNavigationPetHead.appHeadImage, pet!!.imgurl
+ )
+ if (TextUtils.isEmpty(historyDataBean!!.address)) {
+ mGeoCoderViewModel.getLatLonAddress(
+ mMapDeviceBean!!.latitude, mMapDeviceBean!!.longitude
+ )
+ } else mViewBinding.homeMapNavigationAddress.text = historyDataBean!!.address
+
+ warningOutFence()
+ }
+
+ override fun liveDataObserve() {
+ //地理反编译成功返回
+ mGeoCoderViewModel.mLatLonAddressLiveData.observe(this) {
+ mViewBinding.homeMapNavigationAddress.text = it
+ }
+ }
+
+ /***
+ * 设置距离
+ */
+ fun setDistanceData(distanceStr: String, minStr: String) {
+ mViewBinding.apply {
+ mapNavigationDistanceValue.text = distanceStr
+ mapNavigationWalkValue.text = minStr
+ }
+ }
+
+ /**
+ * 宠物出围栏警告
+ */
+ private fun warningOutFence() {
+ //没有出围栏
+// if (mMapDeviceBean!!.inFence == ConstantInt.InFence) {
+// return
+// }
+ val animation =
+ ViewUtil.instance.viewLoadAnimation(mContext, mViewBinding.homeMapNavigationPetLayout)
+ animation.setAnimationListener(object : Animation.AnimationListener {
+ override fun onAnimationStart(animation: Animation?) {
+ mViewBinding.homeMapNavigationPetLayout.visibility = View.VISIBLE
+ }
+
+ override fun onAnimationEnd(animation: Animation?) {
+ val rotationObjectAnimator = ObjectAnimator.ofFloat(
+ mViewBinding.homeMapNavigationPetLayout, "rotation", 0f, 1.6f, 0f - 1.6f
+ )
+ rotationObjectAnimator.duration = 120
+ rotationObjectAnimator.interpolator = AccelerateDecelerateInterpolator()
+ rotationObjectAnimator.repeatMode = ValueAnimator.REVERSE
+ rotationObjectAnimator.repeatCount = ValueAnimator.INFINITE
+ rotationObjectAnimator.start()
+
+ val animation2 = ViewUtil.instance.viewLoadAnimation(
+ mContext!!,
+ mViewBinding.homeMapNavigationPetLayout,
+ R.anim.scale_out_center,
+ startOffset = 8000
+ )
+ animation2.setAnimationListener(object : Animation.AnimationListener {
+ override fun onAnimationStart(animation: Animation?) {
+ }
+
+ override fun onAnimationEnd(animation: Animation?) {
+ mViewBinding.homeMapNavigationPetLayout.visibility = View.GONE
+ }
+
+ override fun onAnimationRepeat(animation: Animation?) {
+ }
+ })
+ }
+
+ override fun onAnimationRepeat(animation: Animation?) {
+ }
+ })
+ }
+
+ /**
+ * 选择地图开始跳转
+ */
+ private fun selectMapNavigation(item: MenuTxtBean) {
+ mSelectMapListDialog?.dismiss()
+ //自动弹出手机中已经有安装地图的应用
+// val mUri: Uri = Uri.parse("geo:227.15" + ",212.55" + "?q=fhfhfg")
+// val mIntent = Intent(Intent.ACTION_VIEW, mUri)
+// startActivity(mIntent)
+ if (AppUtils.isAppInstalled(mContext!!, item.menuValue)) {
+ if (null == mMapDeviceBean) {
+
+ } else {
+ when (item.menuValue) {
+ //选择高德地图
+ mMapGaoDePackageName -> {
+ val uri = "androidamap://navi?sourceApplication=" + getString(
+ R.string.app_name
+ ) + "&lat=${mMapDeviceBean!!.latitude}&lon=${mMapDeviceBean!!.longitude}&dev=0"
+ val intent = Intent.parseUri(uri, 0)
+ startActivity(intent)
+ }
+ //谷歌地图
+ mMapGooglePackageName -> {
+// val latitude = 22.56025
+// val longitude = 113.954032
+ val uri =
+ "google.navigation:q=${mMapDeviceBean!!.latitude},${mMapDeviceBean!!.longitude}"
+ val intent = Intent.parseUri(uri, 0)
+ startActivity(intent)
+ }
+ }
+ }
+ } else {
+ showToast(getString(R.string.txt_no_install))
+ }
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mViewBinding.selectMapNavigationBtn -> {
+ if (null == mSelectMapListDialog) {
+ mSelectMapListDialog =
+ SelectMapListDialog(mContext!!, mSelectMapListDialogAdapter)
+ }
+ mSelectMapListDialog!!.show()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/map/MapLiveActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/map/MapLiveActivity.kt
new file mode 100644
index 0000000..b674827
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/map/MapLiveActivity.kt
@@ -0,0 +1,276 @@
+package com.abbidot.tracker.deprecated.ui.activity.map
+
+import android.animation.ValueAnimator
+import android.view.View
+import androidx.activity.viewModels
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.commit
+import coil.load
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.base.BaseDialog
+import com.abbidot.tracker.bean.FencesBean
+import com.abbidot.tracker.bean.HistoryDataBean
+import com.abbidot.tracker.bean.PetBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.databinding.ActivityMapLiveBinding
+import com.abbidot.tracker.vm.MapLiveViewModel
+import com.abbidot.tracker.vm.FencesManageViewModel
+import com.abbidot.tracker.vm.FencesMapViewModel
+import com.abbidot.tracker.vm.FindBleDeviceViewModel
+import com.abbidot.tracker.vm.TrackerSetViewModel
+import com.abbidot.tracker.ui.common.map.MapLiveCommon
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.abbidot.tracker.util.bluetooth.SRBleCmdUtil
+import com.abbidot.tracker.util.bluetooth.SRBleUtil
+import com.clj.fastble.BleManager
+import com.clj.fastble.data.BleDevice
+import com.daimajia.androidanimations.library.Techniques
+import com.daimajia.androidanimations.library.YoYo
+import com.qmuiteam.qmui.widget.QMUITopBar
+
+/**
+ *MapLive实时监测位置
+ */
+class MapLiveActivity : BaseActivity(ActivityMapLiveBinding::inflate) {
+
+ private val mMapLiveViewModel: MapLiveViewModel by viewModels()
+ val mFencesMapViewModel: FencesMapViewModel by viewModels()
+ val mFencesManageViewModel: FencesManageViewModel by viewModels()
+ private val mTrackerManageViewModel: TrackerSetViewModel by viewModels()
+ private val mFindBleDeviceViewModel: FindBleDeviceViewModel by viewModels()
+ lateinit var mPet: PetBean
+
+ private lateinit var mFragment: Fragment
+ private lateinit var mMapLiveCommon: MapLiveCommon
+
+ //宠物是否在围栏里
+ private var isInFence = -1
+
+ //围栏数据集
+ private val mFencesList = mutableListOf()
+ private var mHistoryDataBean: HistoryDataBean? = null
+ private var mBleDevice: BleDevice? = null
+
+ //动画效果,方便清除动画
+ private var mGpsYoYoAnimString: YoYo.YoYoString? = null
+ private var mBatteryYoYoAnimString: YoYo.YoYoString? = null
+ private var mLiveStatus = 1
+
+ override fun getTopBar(): QMUITopBar? = null
+
+ override fun initData() {
+ super.initData()
+
+ mPet = Util.getParcelableAdaptive(intent, ConstantString.Pet, PetBean::class.java)!!
+
+ mMapLiveCommon = MapLiveCommon()
+ mFragment = mMapLiveCommon.getMapFragment(mContext, mPet.imgurl)
+ supportFragmentManager.commit {
+ add(R.id.map_live_map_view, mFragment)
+ }
+
+ mViewBinding.apply {
+ setOnClickListenerViews(
+ btnStopMapLive, mapLiveDeviceLedSwitch, mapLiveRefreshLocationBtn, btnFindDevice
+ )
+ }
+
+ mMapLiveViewModel.setupDeviceLiveStatus(this, mPet.deviceId, mLiveStatus)
+ }
+
+ override fun liveDataObserve() {
+ mMapLiveViewModel.mMapLiveStatusLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ showLoading(false)
+ if (mLiveStatus == 0) finish()
+ }
+ })
+ }
+
+ mMapLiveViewModel.mMapLiveLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+// setData(data)
+ }
+ })
+ }
+
+ mFencesManageViewModel.mFencesLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+// mFencesList.addAll(data)
+ //获取完围栏数据 再获取宠物 经纬度点 的数据
+ mMapLiveViewModel.getPetLivePoint(mPet.deviceId)
+ }
+ })
+ }
+
+
+ mTrackerManageViewModel.mLedSwitchLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ mViewBinding.mapLiveDeviceLedSwitch.isChecked =
+ !mViewBinding.mapLiveDeviceLedSwitch.isChecked
+ }
+ })
+ }
+ }
+
+ /**
+ * 测试经纬度移动
+ */
+ private var indexX = 0.0
+ private var indexY = 0.0
+
+ private fun setData(historyDataBean: HistoryDataBean) {
+ mHistoryDataBean = historyDataBean
+ if (isInFence != historyDataBean.inFance) {
+ isInFence = historyDataBean.inFance
+ mFencesMapViewModel.setFencesData(mContext, mFencesList, mFragment)
+ }
+ //测试经纬度移动
+// mFencesViewModel.setFencesData(mContext!!, isInFence, mFencesList, mFragment)
+
+ mViewBinding.apply {
+ mapLivePetLayout.mapPetName.text = historyDataBean.petName
+ ViewUtil.instance.imageLoadUrl(
+ mapLivePetLayout.mapPetHead.appHeadImage, historyDataBean.petImgurl
+ )
+ val batteryString =
+ String.format(getString(R.string.txt_battery_unit), historyDataBean.batteryLevel)
+ mapLivePetLayout.mapPetBattery.text = batteryString
+
+ val batteryResId = if (historyDataBean.batteryLevel > ConstantInt.LowBattery20) {
+ mBatteryYoYoAnimString?.stop()
+ R.drawable.ico_map_battery
+ } else {
+ mBatteryYoYoAnimString = null
+ mBatteryYoYoAnimString =
+ YoYo.with(Techniques.FadeIn).repeat(ValueAnimator.INFINITE).duration(1000)
+ .playOn(mapLivePetLayout.mapPetBatteryImage)
+ R.drawable.ico_map_battery_low
+ }
+ mapLivePetLayout.mapPetBatteryImage.load(batteryResId)
+
+ val drawableResId = if (historyDataBean.gnssSignal > ConstantInt.NoSignal) {
+ mGpsYoYoAnimString?.stop()
+ mapLivePetLayout.mapPetGps.text = getString(R.string.txt_online)
+ R.drawable.ico_map_gps
+ } else {
+ mapLivePetLayout.mapPetGps.text = getString(R.string.txt_offline)
+ mGpsYoYoAnimString = null
+ mGpsYoYoAnimString =
+ YoYo.with(Techniques.FadeIn).repeat(ValueAnimator.INFINITE).duration(1000)
+ .playOn(mapLivePetLayout.mapPetGpsImage)
+ R.drawable.ico_gps_no
+ }
+ mapLivePetLayout.mapPetGpsImage.load(drawableResId)
+
+ mapLiveDeviceLedSwitch.isChecked = historyDataBean.ledSwitch == ConstantInt.Open
+
+ mMapLiveCommon.addLine(historyDataBean.latitude, historyDataBean.longitude)
+ }
+
+ //测试经纬度移动
+// if ((Math.random() * 100).toInt() % 2 == 0) {
+// indexX += (Math.random() * 0.02)
+// indexY -= (Math.random() * 0.02)
+// isInFence = ConstantInt.InFence
+// } else {
+// indexX -= (Math.random() * 0.03)
+// indexY += (Math.random() * 0.03)
+// isInFence = ConstantInt.OutFence
+// }
+// mMapLiveBaiduMapFragment?.addLine(indexX, indexY)
+// mMapLiveGoogleMapFragment?.addLine(LatLng(indexX, indexY))
+ }
+
+ override fun onBackPressed() {
+ stopMapLive()
+ }
+
+ private fun stopMapLive() {
+ ViewUtil.instance.showDialog(
+ mContext, R.string.txt_stop_live_tips, object : BaseDialog.OnDialogOkListener {
+ override fun onOkClick(dialog: BaseDialog<*>) {
+ dialog.dismiss()
+ mLiveStatus = 0
+ mMapLiveViewModel.setupDeviceLiveStatus(
+ this@MapLiveActivity, mPet.deviceId, mLiveStatus
+ )
+ }
+ }, okTextResId = R.string.txt_sure
+ )
+ }
+
+ /**
+ * 设置led开关
+ */
+ private fun setLedSwitch() {
+ //屏蔽点击就变状态
+ mViewBinding.mapLiveDeviceLedSwitch.isChecked =
+ !mViewBinding.mapLiveDeviceLedSwitch.isChecked
+ val ledSwitch = if (mViewBinding.mapLiveDeviceLedSwitch.isChecked) {
+ setBleLedMode(mPet.macID, 0)
+ ConstantInt.Close
+ } else {
+ setBleLedMode(mPet.macID, mHistoryDataBean!!.lightMode)
+ ConstantInt.Open
+ }
+ mTrackerManageViewModel.setLedSwitch(this, mHistoryDataBean!!.deviceInfoId, ledSwitch)
+ }
+
+ /**
+ *发送设备蓝牙指令
+ */
+ private fun setBleLedMode(macId: String, mode: Int) {
+ if (null == mBleDevice) {
+ SRBleUtil.instance.getConnectMacDevice(macId)?.apply {
+ mBleDevice = bleDevice
+ }
+ }
+ mBleDevice?.let {
+ if (BleManager.getInstance().isConnected(it)) {
+ SRBleUtil.instance.writeData(
+ it, SRBleCmdUtil.instance.ledState(SRBleCmdUtil.CMD_WRITE, mode)
+ )
+ }
+ }
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mViewBinding.btnStopMapLive -> {
+ stopMapLive()
+ }
+
+ mViewBinding.btnFindDevice -> {
+// mFindBleDeviceViewModel.startScanFind(this, mPet.macID)
+ }
+
+ mViewBinding.mapLiveDeviceLedSwitch -> {
+ setLedSwitch()
+ }
+
+ mViewBinding.mapLiveRefreshLocationBtn -> {
+ ViewUtil.instance.viewAlphaAndRotationObjectAnimator(
+ mViewBinding.mapLiveRefreshLocationBtn
+ )
+ mMapLiveCommon.refreshPetCurrentLocation()
+ }
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ mBatteryYoYoAnimString?.stop()
+ mGpsYoYoAnimString?.stop()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/FencesAddActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/FencesAddActivity.kt
new file mode 100644
index 0000000..688ed59
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/FencesAddActivity.kt
@@ -0,0 +1,502 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile
+
+import android.content.Intent
+import android.graphics.Point
+import android.text.TextUtils
+import android.view.View
+import androidx.activity.viewModels
+import androidx.fragment.app.commit
+import androidx.lifecycle.lifecycleScope
+import com.abbidot.baselibrary.constant.EventName
+import com.abbidot.baselibrary.eventbus.XEventBus
+import com.abbidot.baselibrary.util.LogUtil
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.base.BaseDialog
+import com.abbidot.tracker.bean.FencesBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.databinding.ActivityFencesAddBinding
+import com.abbidot.tracker.ui.common.map.FencesMapCommon
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.abbidot.tracker.vm.FencesManageViewModel
+import com.abbidot.tracker.vm.GeoCoderViewModel
+import com.abbidot.tracker.vm.ScreenshotsViewModel
+import com.abbidot.tracker.vm.UserProfileViewModel
+import com.abbidot.tracker.widget.FencesPolygonView
+import com.abbidot.tracker.widget.OnCircleViewScaleClickListener
+import com.abbidot.tracker.widget.OnRectViewRotateScaleClickListener
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+/***
+ * 添加围栏
+ */
+class FencesAddActivity : BaseActivity(ActivityFencesAddBinding::inflate),
+ FencesMapCommon.OnActivityCallBack, OnRectViewRotateScaleClickListener,
+ OnCircleViewScaleClickListener {
+
+ private val mFencesManageViewModel: FencesManageViewModel by viewModels()
+ private val mScreenshotsViewModel: ScreenshotsViewModel by viewModels()
+ private val mUserInfoViewModel: UserProfileViewModel by viewModels()
+ private val mGeoCoderViewModel: GeoCoderViewModel by viewModels()
+
+ var isEdit = false
+ private lateinit var mDeviceId: String
+ private var mFenceId = ""
+ private var mDeviceServiceId = ""
+
+ //围栏样式
+ var mFenceShapeType = ConstantInt.CircleShapeType
+
+ private lateinit var mFencesMapCommon: FencesMapCommon
+
+ //圆形半径距离
+ private var mCircleRadiusDistance = 0
+
+ //矩形长距离
+ private var mRectWidthDistance = 0
+
+ //矩形宽距离
+ private var mRectHeightDistance = 0
+
+
+ override fun getTopBar() = mViewBinding.fencesAddBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTopBarTitle(R.string.txt_add_fences)
+
+ isEdit = intent.extras!!.getBoolean(ConstantString.Edit, false)
+ mDeviceId = intent.extras!!.getString(ConstantString.DeviceId, "")
+
+ mFencesMapCommon = FencesMapCommon()
+
+ mViewBinding.apply {
+
+ val fragment = mFencesMapCommon.getMapFragment(
+ mContext,
+ searchBaiduMapResultsView,
+ mapboxSearchResultsView,
+ fencesAddSearchAddress,
+ this@FencesAddActivity
+ )
+ supportFragmentManager.commit {
+ add(R.id.fences_add_map_view, fragment)
+ }
+
+ setOnClickListenerViews(
+ fencesSearchAddressBtn, addFencesOkBtn, root
+ )
+ radiogroupFencesShowShapeType.setOnCheckedChangeListener { _, checkedId ->
+ when (checkedId) {
+ R.id.selector_fence_circle_shape -> {
+ if (mFenceShapeType == ConstantInt.CircleShapeType) return@setOnCheckedChangeListener
+ mFenceShapeType = ConstantInt.CircleShapeType
+ }
+
+ R.id.selector_fence_rectangle_shape -> {
+ if (mFenceShapeType == ConstantInt.RectangleShapeType) return@setOnCheckedChangeListener
+ mFenceShapeType = ConstantInt.RectangleShapeType
+ }
+ }
+ setFenceShape(mFenceShapeType)
+ //延迟计算距离
+ if ((mFenceShapeType == ConstantInt.CircleShapeType && mCircleRadiusDistance == 0) || (mFenceShapeType == ConstantInt.RectangleShapeType && mRectHeightDistance == 0 && mRectWidthDistance == 0)) {
+ mViewBinding.fencesAddMapRect.postDelayed(
+ {
+ mFencesMapCommon.refreshDistance()
+ }, 500
+ )
+ } else {
+ showLoading(false)
+ }
+ }
+ fencesAddMapRect.setOnRectViewRotateScaleClickListener(this@FencesAddActivity)
+
+ fencesAddMapCircle.setOnCircleViewScaleClickListener(this@FencesAddActivity)
+
+
+ //编辑
+ if (isEdit) {
+ setTopBarTitle(R.string.txt_edit_fences)
+ mRightImageButton = addRightImageButton(R.drawable.ico_delete)
+ setOnClickListenerViews(mRightImageButton)
+
+ Util.getParcelableAdaptive(intent, ConstantString.Fence, FencesBean::class.java)
+ ?.run {
+ mFenceId = fenceId
+ mDeviceServiceId = deviceServiceId
+ addFencesAddress.text = address
+ addFencesNameEdit.setText(name)
+ addActivateFencesCheckbox.isChecked = isOn == 1
+ mFenceShapeType = fenceType
+ if (fenceType == ConstantInt.CircleShapeType) {
+ fencesAddMapRect.initDefaultWidthHeight()
+ selectorFenceCircleShape.isChecked = true
+ mCircleRadiusDistance = radius
+ mFencesMapCommon.setCenterLatLng(latitude, longitude, radius.toDouble())
+ } else {
+ fencesAddMapCircle.initDefaultRadius()
+ selectorFenceRectangleShape.isChecked = true
+ mRectWidthDistance = longDistance
+ mRectHeightDistance = shortDistance
+ mFencesMapCommon.let {
+ it.setCenterLatLng(latitudeCenter, longitudeCenter)
+ it.setRectABCDLatLng(
+ mContext,
+ longitudeA,
+ latitudeA,
+ longitudeB,
+ latitudeB,
+ longitudeC,
+ latitudeC,
+ longitudeD,
+ latitudeD
+ )
+ }
+ }
+ }
+ } else {
+ fencesAddMapCircle.initDefaultRadius()
+ fencesAddMapRect.initDefaultWidthHeight()
+ }
+ setFenceShape(mFenceShapeType)
+ }
+ }
+
+ override fun liveDataObserve() {
+ //上传图片
+ mUserInfoViewModel.mUploadImageLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ saveFences(it.getOrNull()!!)
+ }
+ })
+ }
+
+ if (isEdit) {
+ mFencesManageViewModel.mDeleteFenceLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ successTips(R.string.txt_delete_success)
+ }
+ })
+ }
+ mFencesManageViewModel.mUpdateFenceLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ successTips(R.string.txt_save_successful)
+ }
+ })
+ }
+
+ } else {
+ mFencesManageViewModel.mFencesAddLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ successTips(R.string.txt_save_successful)
+ }
+ })
+ }
+ }
+
+ //反地理编码
+ mGeoCoderViewModel.mLatLonAddressLiveData.observe(this) {
+ mViewBinding.addFencesAddress.apply {
+ visibility = if (TextUtils.isEmpty(it)) {
+ View.INVISIBLE
+ } else {
+ View.VISIBLE
+ }
+ text = it
+ }
+ }
+
+ //截屏后压缩的图片路径
+ mScreenshotsViewModel.mMapSnapshotPathLiveData.observe(this) {
+ if (!TextUtils.isEmpty(it)) {
+ mUserInfoViewModel.uploadImage(this, it)
+ }
+ }
+ }
+
+ /**
+ * 设置显示哪种围栏样式
+ */
+ private fun setFenceShape(shapeType: Int) {
+ showLoading(true)
+ when (shapeType) {
+ ConstantInt.CircleShapeType -> {
+ mViewBinding.fencesAddMapCircle.visibility = View.VISIBLE
+ mViewBinding.fencesAddMapRect.visibility = View.GONE
+ }
+
+ ConstantInt.RectangleShapeType -> {
+ mViewBinding.fencesAddMapCircle.visibility = View.GONE
+ mViewBinding.fencesAddMapRect.visibility = View.VISIBLE
+ }
+ }
+ }
+
+ /**
+ * 修改成功提示
+ */
+ private fun successTips(resStringId: Int) {
+ XEventBus.post(EventName.UpdateData + "FencesActivity")
+ XEventBus.post(EventName.UpdateData + "MapFences")
+ XEventBus.post(EventName.UpdateData + "TrackerManageSetActivity")
+ showToast(resStringId, isFinish = true)
+ }
+
+ /**
+ * 获取圆形/矩形中心点
+ */
+ fun getCentrePoint() = if (mFenceShapeType == ConstantInt.CircleShapeType) {
+ Point(
+ mViewBinding.fencesAddMapCircle.getCircleCentrePoint()
+ )
+ } else {
+ Point(
+ mViewBinding.fencesAddMapRect.getRectCentrePoint()
+ )
+ }
+
+ /**
+ * 获取圆形直虚线的最后一个点
+ */
+ fun getCircleLineEndPoint() = mViewBinding.fencesAddMapCircle.getCircleLineEndPoint()
+
+ /**
+ * 获取矩形4个点的某一个点
+ */
+ fun getRectABCDPoint(wherePoint: Int) =
+ mViewBinding.fencesAddMapRect.getRectABCDPoint(wherePoint)
+
+ /**
+ * 保存围栏
+ */
+ private fun saveSure() {
+ val fenceName = mViewBinding.addFencesNameEdit.text.toString()
+ val address = mViewBinding.addFencesAddress.text.toString()
+ if (TextUtils.isEmpty(fenceName) || TextUtils.isEmpty(address)) {
+ showToast(R.string.txt_not_null)
+ return
+ }
+
+ val hideDelayMillis = 400L
+ when (mFenceShapeType) {
+ ConstantInt.CircleShapeType -> {
+ mViewBinding.fencesAddMapCircle.apply {
+ //隐藏距离,不被截图
+ setShowHideDisDistance(false)
+ //截屏并上传图片
+ mFencesMapCommon.snapshotImage(
+ this@FencesAddActivity, mScreenshotsViewModel, this
+ )
+ postDelayed({
+ //几秒后开始显示,截屏成功
+ setShowHideDisDistance(true)
+ }, hideDelayMillis)
+ }
+ }
+
+ ConstantInt.RectangleShapeType -> {
+ mViewBinding.fencesAddMapRect.apply {
+ //隐藏距离,不被截图
+ setShowHideDisDistance(false)
+ //截屏并上传图片
+ mFencesMapCommon.snapshotImage(
+ this@FencesAddActivity, mScreenshotsViewModel, this
+ )
+ postDelayed({
+ //几秒后开始显示,截屏成功
+ setShowHideDisDistance(true)
+ }, hideDelayMillis)
+ }
+
+ }
+ }
+ }
+
+ private fun saveFences(imageUrl: String) {
+ val fenceName = mViewBinding.addFencesNameEdit.text.toString()
+ val address = mViewBinding.addFencesAddress.text.toString()
+ val isOn = if (mViewBinding.addActivateFencesCheckbox.isChecked) {
+ 1
+ } else {
+ 0
+ }
+
+ val latLon = mFencesMapCommon.getCenterLatLng()
+ val latitude = latLon[0]
+ val longitude = latLon[1]
+ if (mFenceShapeType == ConstantInt.CircleShapeType) {
+ val radius = mCircleRadiusDistance
+ LogUtil.d("最后的经纬度是,$latitude,$longitude")
+ if (isEdit) {
+ mFencesManageViewModel.updateCircleFence(
+ this, FencesBean()
+ )
+ } else {
+ mFencesManageViewModel.addCircleFence(
+ this, FencesBean()
+ )
+ }
+ } else {
+ val latLonA = mFencesMapCommon.getRectABCDLatLng(FencesPolygonView.POINT_A)
+ val latitudeA = latLonA[0]
+ val longitudeA = latLonA[1]
+ val latLonB = mFencesMapCommon.getRectABCDLatLng(FencesPolygonView.POINT_B)
+ val latitudeB = latLonB[0]
+ val longitudeB = latLonB[1]
+ val latLonC = mFencesMapCommon.getRectABCDLatLng(FencesPolygonView.POINT_C)
+ val latitudeC = latLonC[0]
+ val longitudeC = latLonC[1]
+ val latLonD = mFencesMapCommon.getRectABCDLatLng(FencesPolygonView.POINT_D)
+ val latitudeD = latLonD[0]
+ val longitudeD = latLonD[1]
+ if (isEdit) {
+ mFencesManageViewModel.updateRectFence(
+ this, FencesBean()
+ )
+ } else {
+ mFencesManageViewModel.addRectFence(
+ this, FencesBean()
+ )
+ }
+ }
+
+ }
+
+ /**
+ * 删除围栏
+ */
+ private fun deleteFences() {
+ ViewUtil.instance.showDialog(
+ mContext, R.string.txt_delete_tips, object : BaseDialog.OnDialogOkListener {
+ override fun onOkClick(dialog: BaseDialog<*>) {
+ dialog.dismiss()
+ mFencesManageViewModel.deleteFence(
+ this@FencesAddActivity, mFenceId, mDeviceServiceId
+ )
+ }
+ }, okTextResId = R.string.txt_sure
+ )
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mRightImageButton -> {
+ deleteFences()
+ }
+ //点任意位置隐藏搜索结果
+ mViewBinding.root -> {
+ mFencesMapCommon.setSearchResultsViewGone()
+ }
+
+ mRightImageButton -> {
+ startActivity(Intent(mContext, FencesAddActivity::class.java))
+ }
+
+ mViewBinding.fencesSearchAddressBtn -> {
+ mFencesMapCommon.searchAddress(mViewBinding.fencesAddSearchAddress.text.toString())
+ }
+
+ mViewBinding.addFencesOkBtn -> {
+ saveSure()
+ }
+ }
+ }
+
+ /**
+ * 选点计算距离返回
+ */
+ override fun calculationDistance(distances: Array) {
+ LogUtil.e("选点计算距离返回")
+ if (mFenceShapeType == ConstantInt.CircleShapeType) {
+ mCircleRadiusDistance = Utils.roundOffToInt(distances[0].toDouble())
+ mViewBinding.fencesAddMapCircle.setShowDisDistance("${mCircleRadiusDistance}m")
+ } else {
+ mRectWidthDistance = Utils.roundOffToInt(distances[0].toDouble())
+ mRectHeightDistance = Utils.roundOffToInt(distances[1].toDouble())
+ mViewBinding.fencesAddMapRect.setShowDisDistance(
+ "${mRectWidthDistance}m", "${mRectHeightDistance}m"
+ )
+ }
+ //经纬度转成地址显示
+ mFencesMapCommon.getLatLonAddress(mGeoCoderViewModel)
+ showLoading(false)
+ }
+
+ /**
+ * 地图加载完成返回
+ */
+ override fun mapCompletion() {
+ LogUtil.e("地图加载完成返回")
+ //编辑
+ if (isEdit) {
+ lifecycleScope.launch(Dispatchers.Main) {
+ //等待地图移动摄像头动画播放结束
+ delay(500)
+ LogUtil.e("等待地图移动摄像头动画播放结束")
+ if (mFenceShapeType == ConstantInt.RectangleShapeType) {
+ mFencesMapCommon.let {
+ val pointA = it.latLngToPotion(FencesPolygonView.POINT_A)
+ val pointB = it.latLngToPotion(FencesPolygonView.POINT_B)
+ val pointC = it.latLngToPotion(FencesPolygonView.POINT_C)
+ val pointD = it.latLngToPotion(FencesPolygonView.POINT_D)
+ pointA?.apply {
+ mViewBinding.fencesAddMapRect.apply {
+ setRectABCDXYPoint(pointA, pointA, pointB!!, pointC!!, pointD!!)
+ setShowDisDistance(
+ "${mRectWidthDistance}m", "${mRectHeightDistance}m"
+ )
+ }
+ }
+ LogUtil.e("$pointA,$pointB,$pointC,$pointD")
+ }
+ } else if (mFenceShapeType == ConstantInt.CircleShapeType) {
+ val px = mFencesMapCommon.getCircleRadiusPx(mCircleRadiusDistance.toDouble())
+ mViewBinding.fencesAddMapCircle.apply {
+ setCircleRadiusPx(px.toFloat())
+ setShowDisDistance("${mCircleRadiusDistance}m")
+ }
+ }
+
+ //经纬度转成地址显示,编辑首次进去不需要计算距离
+ mFencesMapCommon.getLatLonAddress(mGeoCoderViewModel)
+ showLoading(false)
+ }
+ }
+ }
+
+ override fun rectRotateClick() {
+ mFencesMapCommon.refreshDistance()
+ }
+
+ override fun rectScaleClick() {
+ mFencesMapCommon.refreshDistance()
+ }
+
+ override fun rectStartDragClick() {
+ }
+
+ override fun rectEndDragClick() {
+ }
+
+ override fun circleScaleClick() {
+ mFencesMapCommon.refreshDistance()
+ }
+
+ override fun circleStartDragClick() {
+ }
+
+ override fun circleEndDragClick() {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/AddCreditCardActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/AddCreditCardActivity.kt
new file mode 100644
index 0000000..363eda9
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/AddCreditCardActivity.kt
@@ -0,0 +1,157 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile.recharge
+
+import android.content.Intent
+import android.text.TextUtils
+import android.view.View
+import androidx.core.widget.addTextChangedListener
+import androidx.lifecycle.lifecycleScope
+import com.abbidot.baselibrary.constant.ResultCode
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.CreditCardBean
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.database.MyDatabase
+import com.abbidot.tracker.databinding.ActivityAddCreditCardBinding
+import com.abbidot.tracker.util.Util
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+/**
+ * 添加信用卡
+ * card.cardNumber = "4111111111111111"
+ *card.expirationDate = "08/20"
+ *card.countryCode = "USA"
+ */
+class AddCreditCardActivity :
+ BaseActivity(ActivityAddCreditCardBinding::inflate),
+ View.OnFocusChangeListener {
+
+ override fun getTopBar() = mViewBinding.addCreditCardBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTopBarTitle(R.string.txt_pay_order_add_card)
+
+ setOnClickListenerViews(mViewBinding.confirmSaveCardBtn)
+
+ mViewBinding.addCreditCardNumberEd.addTextChangedListener {
+ mViewBinding.addCreditCardCardView.setCardNumber(it.toString())
+ }
+ mViewBinding.addCreditCardNameEd.addTextChangedListener {
+ val lastName = mViewBinding.addCreditCardLastNameEd.text.toString()
+ val name = "$lastName " + it.toString()
+ mViewBinding.addCreditCardCardView.setCardholderName(name)
+ }
+ mViewBinding.addCreditCardLastNameEd.addTextChangedListener {
+ val firstName = mViewBinding.addCreditCardNameEd.text.toString()
+ val name = it.toString() + " $firstName"
+ mViewBinding.addCreditCardCardView.setCardholderName(name)
+ }
+ mViewBinding.addCreditCardValidityEd.addTextChangedListener {
+ formatCardExpiry(it.toString())
+ }
+ mViewBinding.addCreditCardCvvEd.addTextChangedListener {
+ mViewBinding.addCreditCardCardView.setCVV(it.toString())
+ }
+
+ mViewBinding.addCreditCardValidityEd.onFocusChangeListener = this
+ mViewBinding.addCreditCardNameEd.onFocusChangeListener = this
+ mViewBinding.addCreditCardLastNameEd.onFocusChangeListener = this
+ mViewBinding.addCreditCardNumberEd.onFocusChangeListener = this
+ mViewBinding.addCreditCardCvvEd.onFocusChangeListener = this
+ }
+
+ /**
+ * 格式化有效期
+ */
+ private fun formatCardExpiry(cardExpiry: String) {
+ var formatCardExpiry = cardExpiry
+ val separator = "/"
+ if (formatCardExpiry.length == 3) {
+ formatCardExpiry = if (formatCardExpiry.contains(separator)) {
+ cardExpiry.substring(0, 2)
+ } else {
+ cardExpiry.substring(0, 2) + separator + cardExpiry.last()
+ }
+ mViewBinding.addCreditCardValidityEd.apply {
+ setText(formatCardExpiry)
+ setSelection(formatCardExpiry.length)
+ }
+ }
+ mViewBinding.addCreditCardCardView.setCardExpiry(formatCardExpiry)
+ }
+
+
+ private fun confirmSaveCard() {
+ val cardNumber = mViewBinding.addCreditCardNumberEd.text.toString()
+ val firstName = mViewBinding.addCreditCardNameEd.text.toString()
+ val lastName = mViewBinding.addCreditCardLastNameEd.text.toString()
+ val creditCardValidity = mViewBinding.addCreditCardValidityEd.text.toString()
+ val cvv = mViewBinding.addCreditCardCvvEd.text.toString()
+
+ if (TextUtils.isEmpty(cardNumber) || TextUtils.isEmpty(firstName) || TextUtils.isEmpty(
+ creditCardValidity) || TextUtils.isEmpty(cvv) || TextUtils.isEmpty(lastName)
+ ) {
+ showToast(R.string.txt_not_null)
+ return
+ }
+
+ if (!creditCardValidity.contains("/")) {
+ showToast(R.string.txt_card_validity_format)
+ return
+ } else {
+ val dates = creditCardValidity.split("/")
+ try {
+ if (dates[0].toInt() > 12) {
+ showToast(R.string.txt_card_validity_format)
+ return
+ }
+ } catch (e: Exception) {
+ showToast(R.string.txt_card_validity_format)
+ return
+ }
+ }
+ if (Util.getCreditCardType(cardNumber) == 0 || cardNumber.length < 9) {
+ showToast(R.string.txt_card_number_format)
+ return
+ }
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ val card = CreditCardBean()
+ card.cardNumber = cardNumber
+ card.lastName = lastName
+ card.firstName = firstName
+ card.expirationDate = creditCardValidity
+ card.cvv = cvv
+ MyDatabase.creditCardDao().insert(card)
+ runOnUiThread {
+ val intent = Intent()
+ intent.putExtra(ConstantString.Card, card)
+ setResult(ResultCode.ResultCode_1, intent)
+ showToast(R.string.txt_save_successful, isFinish = true)
+ }
+ }
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mViewBinding.confirmSaveCardBtn -> {
+ confirmSaveCard()
+ }
+ }
+ }
+
+ override fun onFocusChange(v: View, hasFocus: Boolean) {
+ if (hasFocus) {
+ when (v) {
+ mViewBinding.addCreditCardNumberEd, mViewBinding.addCreditCardNameEd, mViewBinding.addCreditCardLastNameEd, mViewBinding.addCreditCardValidityEd -> {
+ mViewBinding.addCreditCardCardView.showFrontAnimation()
+ }
+ mViewBinding.addCreditCardCvvEd -> {
+ mViewBinding.addCreditCardCardView.showBehindAnimation()
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentMethodPayPalActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentMethodPayPalActivity.kt
new file mode 100644
index 0000000..0dee61a
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentMethodPayPalActivity.kt
@@ -0,0 +1,391 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile.recharge
+
+import android.content.Intent
+import android.text.TextUtils
+import android.view.View
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.activity.viewModels
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.DiffUtil
+import com.abbidot.baselibrary.constant.EventName
+import com.abbidot.baselibrary.constant.ResultCode
+import com.abbidot.baselibrary.eventbus.XEventBus
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.util.LogUtil
+import com.abbidot.tracker.R
+import com.abbidot.tracker.deprecated.adapter.SelectPaymentMethodAdapter
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.CreditCardBean
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.bean.RechargeDeviceBean
+import com.abbidot.tracker.bean.SetMealBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.database.MyDatabase
+import com.abbidot.tracker.databinding.ActivitySelectPaymentMethodBinding
+import com.abbidot.tracker.deprecated.ui.activity.vm.BraintreePalViewModel
+import com.abbidot.tracker.diff.PaymentMethodDiffCallBack
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.braintreepayments.api.BraintreeClient
+import com.braintreepayments.api.Card
+import com.braintreepayments.api.CardClient
+import com.braintreepayments.api.PayPalAccountNonce
+import com.braintreepayments.api.PayPalClient
+import com.braintreepayments.api.PayPalListener
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * 选择支付方式
+ */
+class PaymentMethodPayPalActivity :
+ BaseActivity(ActivitySelectPaymentMethodBinding::inflate),
+ PayPalListener {
+
+ private val mBraintreePalViewModel: BraintreePalViewModel by viewModels()
+
+ private lateinit var mSelectPaymentMethodAdapter: SelectPaymentMethodAdapter
+
+ //设备
+ private var mRechargeDeviceBean: RechargeDeviceBean? = null
+
+ //套餐
+ private var mSetMealBean: SetMealBean? = null
+
+ //已选中的支付方式下标
+ private var mSelectPaymentMethodIndex = 0
+
+ private var mBraintreeClient: BraintreeClient? = null
+
+ //payPal支付
+ private var mPayPalClient: PayPalClient? = null
+
+ //信用卡支付
+ private var mCardClient: CardClient? = null
+
+ //订单号
+ private var mOrderNo = ""
+
+ //0待支付 1是支付成功 2是取消支付/失败
+ private var mOrderStatus = 0
+
+ override fun getTopBar() = mViewBinding.selectPaymentMethodBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTopBarTitle(R.string.txt_pay_order_method)
+
+ intent.extras?.apply {
+ mRechargeDeviceBean = Util.getParcelableAdaptive(
+ intent, ConstantString.RechargeDevice, RechargeDeviceBean::class.java
+ )
+ mSetMealBean =
+ Util.getParcelableAdaptive(intent, ConstantString.SetMeal, SetMealBean::class.java)
+ }
+
+ setData()
+
+ setOnClickListenerViews(mViewBinding.sureSelectPaymentMethodBtn)
+ }
+
+ private fun setData() {
+ lifecycleScope.launch {
+
+ val paymentMethodList = mutableListOf()
+
+ withContext(Dispatchers.IO) {
+ ViewUtil.instance.addMenuBean(paymentMethodList, "", "", R.drawable.ico_lay_paypal)
+
+ val list = MyDatabase.creditCardDao().findAll(MyDatabase.CreditCardTableName)
+ list?.forEach {
+ val imageId = Util.getCreditCardType(it.cardNumber)
+ ViewUtil.instance.addMenuBean(
+ paymentMethodList, it.cardNumber, it.expirationDate, imageId
+ )
+ }
+
+ ViewUtil.instance.addMenuBean(
+ paymentMethodList,
+ getString(R.string.txt_pay_order_add_card),
+ "",
+ R.drawable.ico_lay_newcard
+ )
+ }
+
+ mSelectPaymentMethodAdapter = SelectPaymentMethodAdapter(mContext!!, paymentMethodList)
+ mSelectPaymentMethodAdapter.setOnItemClickListener(object :
+ BaseRecyclerAdapter.OnItemClickListener {
+ override fun onItemClick(itemView: View?, pos: Int) {
+ selectPaymentMethod(pos)
+ }
+ })
+ ViewUtil.instance.setRecyclerViewVerticalLinearLayout(
+ mContext!!,
+ mViewBinding.paymentMethodRecyclerView,
+ mSelectPaymentMethodAdapter,
+ bottom = 40
+ )
+ }
+
+ }
+
+ override fun liveDataObserve() {
+
+ mBraintreePalViewModel.mPayPalOrderNoLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ mOrderNo = it.getOrNull()!!.orderNo
+ mBraintreePalViewModel.getBraintreeClientToken(this@PaymentMethodPayPalActivity)
+ }
+ })
+ }
+
+ /**
+ * 获取Braintree客户端令牌key
+ */
+ mBraintreePalViewModel.mBraintreeClientTokenLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+ lifecycleScope.launch {
+ withContext(Dispatchers.IO) {
+ if (null == mBraintreeClient) {
+ //显示支付 UI 之前,使用您的令牌化密钥初始化 SDK
+ mBraintreeClient = BraintreeClient(mContext, data.tokenId)
+ }
+ }
+ if (null != mBraintreeClient) {
+ if (mSelectPaymentMethodIndex == 0) {
+ launchPayPal()
+ } else {
+ launchCardPay()
+ }
+ } else {
+ showToast(R.string.txt_pay_fail)
+ }
+ }
+ }
+ }, showLoading = true)
+ }
+
+ XEventBus.observe(this, EventName.PayBack) {
+ finish()
+ }
+
+ /**
+ * 更新订单
+ */
+ mBraintreePalViewModel.mUpdateOrderStatusLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ if (mOrderStatus == 1) {
+ payPalSuccess()
+ } else {
+ payPalFail()
+ }
+ }
+ })
+ }
+
+ //信用卡支付成功
+ mBraintreePalViewModel.mCardPaymentResultLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+ if (!TextUtils.isEmpty(data)) {
+ payPalSuccess()
+// if (data == ErrorCode.CREDIT_CARD_PAY_SUCCESS.toString()) {
+// payPalSuccess()
+// } else {
+// payPalFail()
+// }
+ }
+ }
+ })
+ }
+ }
+
+ override fun onNewIntent(newIntent: Intent) {
+ super.onNewIntent(newIntent)
+ // required if your activity's launch mode is "singleTop", "singleTask", or "singleInstance"
+ intent = newIntent
+ }
+
+ /**
+ * 选择一种支付方式
+ */
+ private fun selectPaymentMethod(pos: Int) {
+ val oldList = mSelectPaymentMethodAdapter.getData()
+ //处理最后一个选项 直接添跳转加信用卡
+ if (pos == oldList.size - 1) {
+ val intent = Intent(mContext, AddCreditCardActivity::class.java)
+ launchActivity(mActivityResultLauncher, intent)
+ return
+ }
+ if (oldList[pos].isSwitch) {
+ return
+ }
+
+ val newList = mutableListOf()
+ oldList.forEach {
+ ViewUtil.instance.addMenuBean(
+ newList, it.menuName, it.menuValue, it.imageId, isSwitch = it.isSwitch
+ )
+ }
+ newList[mSelectPaymentMethodIndex].isSwitch = false
+ newList[pos].isSwitch = true
+ mSelectPaymentMethodIndex = pos
+ lifecycleScope.launch {
+ withContext(Dispatchers.Default) {
+ mSelectPaymentMethodAdapter.setData(newList)
+ DiffUtil.calculateDiff(PaymentMethodDiffCallBack(oldList, newList), true)
+ }.dispatchUpdatesTo(mSelectPaymentMethodAdapter)
+ }
+ }
+
+ /**
+ * 接收添加信用卡返回结果
+ */
+ private val mActivityResultLauncher =
+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+ if (null != it.data) {
+ if (it.resultCode == ResultCode.ResultCode_1) {
+ val card = Util.getParcelableAdaptive(
+ it.data!!, ConstantString.Card, CreditCardBean::class.java
+ )
+ if (null != card) {
+ mBraintreePalViewModel.addCreditCard(
+ this, card, mSelectPaymentMethodAdapter
+ )
+ }
+ }
+ }
+ }
+
+
+ /**
+ * 确认支付
+ */
+ private fun surePay() {
+ val list = mSelectPaymentMethodAdapter.getData()
+ var selectPaymentMethodIndex = -1
+ for (i in 0 until list.size) {
+ if (list[i].isSwitch) {
+ selectPaymentMethodIndex = i
+ break
+ }
+ }
+
+ if (selectPaymentMethodIndex == -1) {
+ showToast(R.string.txt_select_payment_method)
+ return
+ }
+ mSelectPaymentMethodIndex = selectPaymentMethodIndex
+
+ if (mSelectPaymentMethodIndex == 0) {
+ mBraintreePalViewModel.getPaypalOrderNo(
+ this, mSetMealBean!!, mRechargeDeviceBean!!.deviceId
+ )
+ } else {
+ //信用卡支付不需要订单号
+ mBraintreePalViewModel.getBraintreeClientToken(this@PaymentMethodPayPalActivity)
+ }
+ }
+
+ /**
+ * 开始PayPal支付
+ */
+ private fun launchPayPal() {
+ if (null == mPayPalClient) {
+ mPayPalClient = PayPalClient(this, mBraintreeClient!!)
+ mPayPalClient!!.setListener(this)
+ }
+ mBraintreePalViewModel.launchPayPal(
+ this, mBraintreeClient, mPayPalClient, mSetMealBean, mOrderNo
+ )
+ }
+
+ /**
+ * 开始信用卡支付
+ */
+ private fun launchCardPay() {
+ lifecycleScope.launch {
+ withContext(Dispatchers.IO) {
+ if (null == mCardClient) {
+ mCardClient = CardClient(mBraintreeClient!!)
+ }
+ }
+ val creditCardBean = mSelectPaymentMethodAdapter.getData()[mSelectPaymentMethodIndex]
+ val card = Card()
+ card.number = creditCardBean.menuName
+ card.expirationDate = creditCardBean.menuValue
+ card.countryCode = "USA"
+ mBraintreePalViewModel.launchCardPay(
+ this@PaymentMethodPayPalActivity,
+ mCardClient,
+ card,
+ mSetMealBean,
+ mRechargeDeviceBean!!.deviceId
+ )
+ }
+ }
+
+ /**
+ * 支付成功
+ */
+ private fun payPalSuccess() {
+ val intent = Intent(mContext!!, PaymentResultActivity::class.java)
+ intent.putExtra(ConstantString.Amount, mSetMealBean!!.accountFee)
+ intent.putExtra(ConstantString.Type, ConstantInt.Type1)
+ startActivityFinish(intent)
+ }
+
+ /**
+ * 支付失败
+ */
+ private fun payPalFail() {
+ val intent = Intent(mContext!!, PaymentResultActivity::class.java)
+ intent.putExtra(ConstantString.Type, ConstantInt.Type2)
+ startActivity(intent)
+ }
+
+ /**
+ * PayPal支付回调
+ */
+ override fun onPayPalSuccess(payPalAccountNonce: PayPalAccountNonce) {
+ LogUtil.e("PayPal支付成功${payPalAccountNonce}")
+ mOrderStatus = 1
+// showToast(R.string.txt_pay_success)
+ mBraintreePalViewModel.updateOrderStatus(
+ this, mOrderNo, mOrderStatus, mRechargeDeviceBean!!.deviceId, mSetMealBean!!.days
+ )
+ }
+
+ /**
+ * PayPal支付回调
+ */
+ override fun onPayPalFailure(error: Exception) {
+ val message = error.message
+ mOrderStatus = 2
+ LogUtil.e("PayPal支付失败$message")
+// if (message?.contains("cancel") == true) {
+// showToast(R.string.txt_user_canceled_paypal)
+// } else {
+// showToast(R.string.txt_pay_fail)
+// }
+ mBraintreePalViewModel.updateOrderStatus(
+ this, mOrderNo, mOrderStatus, mRechargeDeviceBean!!.deviceId, mSetMealBean!!.days
+ )
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mViewBinding.sureSelectPaymentMethodBtn -> {
+ surePay()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentMethodStripeActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentMethodStripeActivity.kt
new file mode 100644
index 0000000..df58bff
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentMethodStripeActivity.kt
@@ -0,0 +1,485 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile.recharge
+
+import android.content.Intent
+import android.text.TextUtils
+import android.view.View
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.activity.viewModels
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.DiffUtil
+import com.abbidot.baselibrary.constant.EventName
+import com.abbidot.baselibrary.constant.ResultCode
+import com.abbidot.baselibrary.eventbus.XEventBus
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.util.LogUtil
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.CreditCardBean
+import com.abbidot.tracker.bean.LKSimSetMealBean
+import com.abbidot.tracker.bean.MenuTxtBean
+import com.abbidot.tracker.bean.RechargeDeviceBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.database.MyDatabase
+import com.abbidot.tracker.databinding.ActivitySelectPaymentMethodBinding
+import com.abbidot.tracker.deprecated.adapter.SelectPaymentMethodAdapter
+import com.abbidot.tracker.deprecated.ui.activity.vm.BraintreePalViewModel
+import com.abbidot.tracker.deprecated.ui.activity.vm.StripePalViewModel
+import com.abbidot.tracker.diff.PaymentMethodDiffCallBack
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.braintreepayments.api.BraintreeClient
+import com.braintreepayments.api.Card
+import com.braintreepayments.api.CardClient
+import com.braintreepayments.api.PayPalAccountNonce
+import com.braintreepayments.api.PayPalClient
+import com.braintreepayments.api.PayPalListener
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * 选择支付方式
+ */
+class PaymentMethodStripeActivity :
+ BaseActivity(ActivitySelectPaymentMethodBinding::inflate),
+ PayPalListener {
+
+ private val mBraintreePalViewModel: BraintreePalViewModel by viewModels()
+ private val mStripePalViewModel: StripePalViewModel by viewModels()
+
+ private lateinit var mSelectPaymentMethodAdapter: SelectPaymentMethodAdapter
+
+ //设备
+ private var mRechargeDeviceBean: RechargeDeviceBean? = null
+
+ //套餐
+ private var mLKSimSetMealBean: LKSimSetMealBean? = null
+
+ //已选中的支付方式下标
+ private var mSelectPaymentMethodIndex = 0
+
+ private var mBraintreeClient: BraintreeClient? = null
+
+ //payPal支付
+ private var mPayPalClient: PayPalClient? = null
+
+ //信用卡支付
+ private var mCardClient: CardClient? = null
+
+ //订单号
+ private var mOrderNo = ""
+ private var mPartnerCode = ""
+
+ //0待支付 1是支付成功 2是取消支付/失败
+ private var mOrderStatus = 0
+
+ //mealType套餐类型
+ private var mSetMealIndex = 0
+
+ override fun getTopBar() = mViewBinding.selectPaymentMethodBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTopBarTitle(R.string.txt_pay_order_method)
+
+ intent.extras?.apply {
+ mRechargeDeviceBean = Util.getParcelableAdaptive(
+ intent, ConstantString.RechargeDevice, RechargeDeviceBean::class.java
+ )
+ mLKSimSetMealBean = Util.getParcelableAdaptive(
+ intent, ConstantString.LkSetMeal, LKSimSetMealBean::class.java
+ )
+ mPartnerCode = getString(ConstantString.PartnerCode).toString()
+ mSetMealIndex = getInt(ConstantString.SetMealIndex, 0)
+
+ setData()
+
+ setOnClickListenerViews(mViewBinding.sureSelectPaymentMethodBtn)
+
+ //Stripe普通支付
+ if (mLKSimSetMealBean!!.specAndPriceList!![0].autoRenewal == "0") {
+ mStripePalViewModel.init(this@PaymentMethodStripeActivity)
+ }
+ }
+ }
+
+ private fun setData() {
+ lifecycleScope.launch {
+
+ val paymentMethodList = mutableListOf()
+
+ withContext(Dispatchers.IO) {
+// ViewUtil.instance.addMenuBean(paymentMethodList, "", "", R.drawable.ico_lay_paypal)
+
+ val list = MyDatabase.creditCardDao().findAll(MyDatabase.CreditCardTableName)
+ list?.forEach {
+ val imageId = Util.getCreditCardType(it.cardNumber)
+ ViewUtil.instance.addMenuBean(
+ paymentMethodList, it.cardNumber, it.expirationDate, imageId
+ )
+ }
+
+ ViewUtil.instance.addMenuBean(
+ paymentMethodList,
+ getString(R.string.txt_pay_order_add_card),
+ "",
+ R.drawable.ico_lay_newcard
+ )
+ }
+
+ mSelectPaymentMethodAdapter =
+ SelectPaymentMethodAdapter(mContext!!, paymentMethodList, false)
+ mSelectPaymentMethodAdapter.setOnItemClickListener(object :
+ BaseRecyclerAdapter.OnItemClickListener {
+ override fun onItemClick(itemView: View?, pos: Int) {
+ selectPaymentMethod(pos)
+ }
+ })
+ ViewUtil.instance.setRecyclerViewVerticalLinearLayout(
+ mContext!!,
+ mViewBinding.paymentMethodRecyclerView,
+ mSelectPaymentMethodAdapter,
+ bottom = 40
+ )
+ }
+
+ }
+
+ override fun liveDataObserve() {
+ /*************************Stripe支付************************************/
+ mStripePalViewModel.mStripePayOrderNoLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val clientSecret = it.getOrNull()
+ clientSecret?.let { secret ->
+ mStripePalViewModel.mPaymentIntentClientSecret = secret
+ launchStripePal()
+ }
+ }
+ })
+ }
+
+// mStripePalViewModel.mStripeSubscriptionCustomerLiveData.observe(this) {
+// dealRequestResult(it, object : GetResultCallback {
+// override fun onResult(any: Any) {
+// val data = it.getOrNull()
+// data?.apply {
+// mStripePalViewModel.createSubscription(
+// this@PaymentMethodStripeActivity,
+// mLKSimSetMealBean!!,
+// this,
+// mRechargeDeviceBean!!,
+// mPartnerCode
+// )
+// }
+// }
+// })
+// }
+
+ mStripePalViewModel.mStripeSubscriptionLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+ if (!TextUtils.isEmpty(data)) {
+ payPalSuccess()
+ }
+ }
+ })
+ }
+
+ //Stripe支付结果
+ mStripePalViewModel.mStripePayResultLiveData.observe(this) {
+ showLoading(false)
+ it?.apply {
+ when (it) {
+ 0 -> payPalSuccess()
+ 1 -> payPalFail()
+ -1 -> {
+ showToast(R.string.txt_user_canceled_paypal, true)
+ }
+ }
+ }
+ }
+ /*************************Stripe支付************************************/
+
+ mBraintreePalViewModel.mPayPalOrderNoLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ mOrderNo = it.getOrNull()!!.orderNo
+ mBraintreePalViewModel.getBraintreeClientToken(this@PaymentMethodStripeActivity)
+ }
+ })
+ }
+
+ /**
+ * 获取Braintree客户端令牌key
+ */
+ mBraintreePalViewModel.mBraintreeClientTokenLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+ lifecycleScope.launch {
+ withContext(Dispatchers.IO) {
+ if (null == mBraintreeClient) {
+ //显示支付 UI 之前,使用您的令牌化密钥初始化 SDK
+ mBraintreeClient = BraintreeClient(mContext!!, data.tokenId)
+ }
+ }
+ if (null != mBraintreeClient) {
+ if (mSelectPaymentMethodIndex == 0) {
+ launchPayPal()
+ } else {
+ launchCardPay()
+ }
+ } else {
+ showToast(R.string.txt_pay_fail)
+ }
+ }
+ }
+ }, showLoading = true)
+ }
+
+ XEventBus.observe(this, EventName.PayBack) {
+ finish()
+ }
+
+ /**
+ * 更新订单
+ */
+ mBraintreePalViewModel.mUpdateOrderStatusLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ if (mOrderStatus == 1) {
+ payPalSuccess()
+ } else {
+ payPalFail()
+ }
+ }
+ })
+ }
+
+ //信用卡支付成功
+ mBraintreePalViewModel.mCardPaymentResultLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+ if (!TextUtils.isEmpty(data)) {
+ payPalSuccess()
+// if (data == ErrorCode.CREDIT_CARD_PAY_SUCCESS.toString()) {
+// payPalSuccess()
+// } else {
+// payPalFail()
+// }
+ }
+ }
+ })
+ }
+ }
+
+ override fun onNewIntent(newIntent: Intent) {
+ super.onNewIntent(newIntent)
+ // required if your activity's launch mode is "singleTop", "singleTask", or "singleInstance"
+ intent = newIntent
+ }
+
+ /**
+ * 选择一种支付方式
+ */
+ private fun selectPaymentMethod(pos: Int) {
+ val oldList = mSelectPaymentMethodAdapter.getData()
+ //处理最后一个选项 直接添跳转加信用卡
+ if (pos == oldList.size - 1) {
+ val intent = Intent(mContext, AddCreditCardActivity::class.java)
+ launchActivity(mActivityResultLauncher, intent)
+ return
+ }
+ if (oldList[pos].isSwitch) {
+ return
+ }
+
+ val newList = mutableListOf()
+ oldList.forEach {
+ ViewUtil.instance.addMenuBean(
+ newList, it.menuName, it.menuValue, it.imageId, isSwitch = it.isSwitch
+ )
+ }
+ newList[mSelectPaymentMethodIndex].isSwitch = false
+ newList[pos].isSwitch = true
+ mSelectPaymentMethodIndex = pos
+ //更新选中的某个支付方式
+ lifecycleScope.launch {
+ withContext(Dispatchers.Default) {
+ mSelectPaymentMethodAdapter.setData(newList)
+ DiffUtil.calculateDiff(PaymentMethodDiffCallBack(oldList, newList), true)
+ }.dispatchUpdatesTo(mSelectPaymentMethodAdapter)
+ }
+ }
+
+ /**
+ * 接收添加信用卡返回结果
+ */
+ private val mActivityResultLauncher =
+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+ if (null != it.data) {
+ if (it.resultCode == ResultCode.ResultCode_1) {
+ val card = Util.getParcelableAdaptive(
+ it.data!!, ConstantString.Card, CreditCardBean::class.java
+ )
+ if (null != card) {
+ mBraintreePalViewModel.addCreditCard(
+ this, card, mSelectPaymentMethodAdapter
+ )
+ }
+ }
+ }
+ }
+
+
+ /**
+ * 确认支付
+ */
+ private fun surePay() {
+ val list = mSelectPaymentMethodAdapter.getData()
+ var selectPaymentMethodIndex = -1
+ for (i in 0 until list.size) {
+ if (list[i].isSwitch) {
+ selectPaymentMethodIndex = i
+ break
+ }
+ }
+
+ if (selectPaymentMethodIndex == -1) {
+ showToast(R.string.txt_select_payment_method)
+ return
+ }
+ mSelectPaymentMethodIndex = selectPaymentMethodIndex
+
+ //判断是Stripe普通支付还是自动订阅
+ if (mLKSimSetMealBean!!.specAndPriceList!![0].autoRenewal == "0") {
+ //普通支付
+ mStripePalViewModel.getStripePayOrderNo(
+ this, mLKSimSetMealBean!!, mRechargeDeviceBean!!, mPartnerCode
+ )
+ } else {
+ //自动订阅
+ val card = mSelectPaymentMethodAdapter.getData()[mSelectPaymentMethodIndex]
+// mStripePalViewModel.createCustomer(this, card, mSetMealIndex + 1)
+ }
+
+
+// if (mSelectPaymentMethodIndex == 0) {
+// mBraintreePalViewModel.getPaypalOrderNo(
+// this, mSetMealBean!!, mRechargeDeviceBean!!.deviceId
+// )
+// } else {
+// //信用卡支付不需要订单号
+// mBraintreePalViewModel.getBraintreeClientToken(this@PaymentMethodStripeActivity)
+// }
+ }
+
+ /**
+ * 开始PayPal支付
+ */
+ private fun launchPayPal() {
+ if (null == mPayPalClient) {
+ mPayPalClient = PayPalClient(this, mBraintreeClient!!)
+ mPayPalClient!!.setListener(this)
+ }
+// mBraintreePalViewModel.launchPayPal(
+// this, mBraintreeClient, mPayPalClient, mSetMealBean, mOrderNo
+// )
+ }
+
+ /**
+ * 开始信用卡支付
+ */
+ private fun launchCardPay() {
+ lifecycleScope.launch {
+ withContext(Dispatchers.IO) {
+ if (null == mCardClient) {
+ mCardClient = CardClient(mBraintreeClient!!)
+ }
+ }
+ val creditCardBean = mSelectPaymentMethodAdapter.getData()[mSelectPaymentMethodIndex]
+ val card = Card()
+ card.number = creditCardBean.menuName
+ card.expirationDate = creditCardBean.menuValue
+ card.countryCode = "USA"
+// mBraintreePalViewModel.launchCardPay(
+// this@PaymentMethodStripeActivity,
+// mCardClient,
+// card,
+// mSetMealBean,
+// mRechargeDeviceBean!!.deviceId
+// )
+ }
+ }
+
+ /**
+ * 开始Stripe普通支付
+ */
+ private fun launchStripePal() {
+ val card = mSelectPaymentMethodAdapter.getData()[mSelectPaymentMethodIndex]
+ mStripePalViewModel.startCheckout(this, card)
+ }
+
+ /**
+ * 支付成功
+ */
+ private fun payPalSuccess() {
+ val intent = Intent(mContext!!, PaymentResultActivity::class.java)
+ intent.putExtra(
+ ConstantString.Amount, mLKSimSetMealBean!!.specAndPriceList!![0].discountPriceUSD
+ )
+ intent.putExtra(ConstantString.Type, ConstantInt.Type1)
+ startActivityFinish(intent)
+ }
+
+ /**
+ * 支付失败
+ */
+ private fun payPalFail() {
+ val intent = Intent(mContext!!, PaymentResultActivity::class.java)
+ intent.putExtra(ConstantString.Type, ConstantInt.Type2)
+ startActivity(intent)
+ }
+
+ /**
+ * PayPal支付回调
+ */
+ override fun onPayPalSuccess(payPalAccountNonce: PayPalAccountNonce) {
+ LogUtil.e("PayPal支付成功${payPalAccountNonce}")
+ mOrderStatus = 1
+//// showToast(R.string.txt_pay_success)
+// mBraintreePalViewModel.updateOrderStatus(
+// this, mOrderNo, mOrderStatus, mRechargeDeviceBean!!.deviceId, mSetMealBean!!.days
+// )
+ }
+
+ /**
+ * PayPal支付回调
+ */
+ override fun onPayPalFailure(error: Exception) {
+ val message = error.message
+ mOrderStatus = 2
+ LogUtil.e("PayPal支付失败$message")
+//// if (message?.contains("cancel") == true) {
+//// showToast(R.string.txt_user_canceled_paypal)
+//// } else {
+//// showToast(R.string.txt_pay_fail)
+//// }
+// mBraintreePalViewModel.updateOrderStatus(
+// this, mOrderNo, mOrderStatus, mRechargeDeviceBean!!.deviceId, mSetMealBean!!.days
+// )
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mViewBinding.sureSelectPaymentMethodBtn -> {
+ surePay()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentResultActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentResultActivity.kt
new file mode 100644
index 0000000..abf82a7
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/PaymentResultActivity.kt
@@ -0,0 +1,64 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile.recharge
+
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.commit
+import com.abbidot.baselibrary.constant.EventName
+import com.abbidot.baselibrary.eventbus.XEventBus
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.databinding.ActivityPaymentResultBinding
+import com.abbidot.tracker.deprecated.ui.fragment.profile.PaymentFailFragment
+import com.abbidot.tracker.deprecated.ui.fragment.profile.PaymentSuccessFragment
+
+/**
+ * 付款结果显示
+ */
+class PaymentResultActivity :
+ BaseActivity(ActivityPaymentResultBinding::inflate) {
+
+ var mAmount = 0.0
+
+ //成功支付的标识
+ private var isPaymentSuccess = false
+
+ override fun getTopBar() = mViewBinding.paymentResultBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTopBarTitle(R.string.txt_pay_order_payment_title)
+ setLeftBackImage(R.drawable.icon_white_back_svg)
+
+ var type = ConstantInt.Type1
+ intent.extras?.apply {
+ type = getInt(ConstantString.Type)
+ mAmount = getDouble(ConstantString.Amount, 0.0)
+ }
+
+ if (type == ConstantInt.Type1) {
+ isPaymentSuccess = true
+ switchFragment(PaymentSuccessFragment.newInstance(mContext), 0)
+ } else {
+ switchFragment(PaymentFailFragment.newInstance(mContext), 1)
+ }
+ }
+
+ override fun leftBackOnClick() {
+ XEventBus.post(EventName.PayBack)
+ if (isPaymentSuccess) {
+ XEventBus.post(EventName.UpdateData + "PaymentSuccess")
+ }
+ super.leftBackOnClick()
+ }
+
+ fun switchFragment(fragment: Fragment, index: Int) {
+ supportFragmentManager.commit {
+ if (fragment.isAdded) {
+ show(fragment)
+ } else {
+ add(R.id.payment_result_frame, fragment)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeAmountCNActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeAmountCNActivity.kt
new file mode 100644
index 0000000..519be7a
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeAmountCNActivity.kt
@@ -0,0 +1,100 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile.recharge.cn
+
+import android.content.Intent
+import android.view.View
+import androidx.activity.viewModels
+import com.abbidot.baselibrary.constant.EventName
+import com.abbidot.baselibrary.eventbus.XEventBus
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.RechargeDeviceBean
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.databinding.ActivityRechargeAmountCnBinding
+import com.abbidot.tracker.deprecated.adapter.RechargeAmountCNAdapter
+import com.abbidot.tracker.deprecated.ui.activity.vm.RechargeAmountViewModel
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.qmuiteam.qmui.util.QMUIDisplayHelper
+
+/**
+ * 国内套餐列表
+ */
+class RechargeAmountCNActivity :
+ BaseActivity(ActivityRechargeAmountCnBinding::inflate) {
+
+ private val mRechargeAmountViewModel: RechargeAmountViewModel by viewModels()
+
+ private lateinit var mRechargeAmountCNAdapter: RechargeAmountCNAdapter
+ private var mRechargeDeviceBean: RechargeDeviceBean? = null
+
+ override fun getTopBar() = mViewBinding.rechargeAmountCnBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTopBarTitle(R.string.txt_pay_amount)
+
+ //充值设备数据
+ mRechargeDeviceBean = Util.getParcelableAdaptive(
+ intent,
+ ConstantString.RechargeDevice,
+ RechargeDeviceBean::class.java
+ )
+
+ mRechargeAmountCNAdapter = RechargeAmountCNAdapter(this, null)
+ mRechargeAmountCNAdapter.setOnItemClickListener(object :
+ BaseRecyclerAdapter.OnItemClickListener {
+ override fun onItemClick(itemView: View?, pos: Int) {
+ mRechargeAmountCNAdapter.setSelectIndex(pos)
+ }
+ })
+ ViewUtil.instance.setRecyclerViewGridLayout(
+ mContext!!,
+ mViewBinding.rechargeAmountCnRecyclerView,
+ mRechargeAmountCNAdapter,
+ 2,
+ bottom = QMUIDisplayHelper.dpToPx(28),
+ )
+
+ setOnClickListenerViews(mViewBinding.btnRechargeAmountCnSubmitOrder)
+
+ mRechargeAmountViewModel.getSetMealList(this)
+ }
+
+ override fun liveDataObserve() {
+ XEventBus.observe(this, EventName.PayBack) {
+ finish()
+ }
+
+ mRechargeAmountViewModel.mSetMealListLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+ mRechargeAmountCNAdapter.setData(data, true)
+ }
+ })
+ }
+ }
+
+ /**
+ * 提交订单
+ */
+ private fun submitOrder() {
+ val index = mRechargeAmountCNAdapter.getSelectIndex()
+ if (index == -1) {
+ showToast(R.string.txt_pay_amount)
+ return
+ }
+ val intent = Intent(mContext, RechargeOrderDetailCNActivity::class.java)
+ intent.putExtra(ConstantString.RechargeDevice, mRechargeDeviceBean)
+ intent.putExtra(ConstantString.SetMeal, mRechargeAmountCNAdapter.getData()[index])
+ startActivity(intent)
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mViewBinding.btnRechargeAmountCnSubmitOrder -> submitOrder()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeDeviceDetailCNActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeDeviceDetailCNActivity.kt
new file mode 100644
index 0000000..e02f916
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeDeviceDetailCNActivity.kt
@@ -0,0 +1,127 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile.recharge.cn
+
+import android.content.Intent
+import android.text.TextUtils
+import android.view.View
+import androidx.activity.viewModels
+import com.abbidot.baselibrary.constant.EventName
+import com.abbidot.baselibrary.eventbus.XEventBus
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.RechargeDeviceBean
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.databinding.ActivityRechargeDeviceDetailCnBinding
+import com.abbidot.tracker.deprecated.ui.activity.vm.RechargeDeviceViewModel
+import com.abbidot.tracker.util.ViewUtil
+
+/**
+ * 设备充值国内详情
+ */
+class RechargeDeviceDetailCNActivity : BaseActivity(
+ ActivityRechargeDeviceDetailCnBinding::inflate) {
+
+ private val mRechargeDeviceViewModel: RechargeDeviceViewModel by viewModels()
+
+ private var mDeviceId = ""
+
+ //传递给下个页面需要用的值
+ private var mRechargeDeviceBean: RechargeDeviceBean? = null
+
+ override fun getTopBar() = mViewBinding.rechargeDeviceDetailCnBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ mDeviceId = intent.extras?.getString(ConstantString.DeviceId, "").toString()
+ setTopBarTitle(mDeviceId)
+
+ ViewUtil.instance.setShapeRadius(mViewBinding.rechargeDeviceDetailCnDevice.root, 6)
+
+ mViewBinding.rechargeDeviceDetailCnHistory.apply {
+ ViewUtil.instance.showQMUICommonListItemView(mContext!!, this, {
+ val intent = Intent(mContext, RechargeHistoryCNActivity::class.java)
+ intent.putExtra(ConstantString.DeviceId, mDeviceId)
+ startActivity(intent)
+ }, getString(R.string.txt_card_history))
+ detailText = ""
+ }
+
+ setOnClickListenerViews(mViewBinding.btnRechargeDeviceDetailCnRecharge)
+
+ mRechargeDeviceViewModel.getCards(this)
+ }
+
+ override fun liveDataObserve() {
+ mRechargeDeviceViewModel.mDeviceCardLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()!!
+ setData(data)
+ }
+ })
+ }
+
+ //充值成功刷新天数
+ XEventBus.observe(this, EventName.UpdateData + "PaymentSuccess") {
+ mRechargeDeviceViewModel.getCards(this)
+ }
+ }
+
+ private fun setData(list: MutableList) {
+ for (i in 0 until list.size) {
+ val rechargeDeviceBean = list[i]
+ if (mDeviceId == rechargeDeviceBean.deviceId) {
+ mRechargeDeviceBean = rechargeDeviceBean
+ mTopBar?.setTitle(rechargeDeviceBean.deviceOutId)
+ mViewBinding.rechargeDeviceDetailCnDevice.apply {
+ itemCardDeviceName.text = rechargeDeviceBean.deviceOutId
+ itemCardDayNumber.text = rechargeDeviceBean.surplusDays.toString()
+ val overdueDate = rechargeDeviceBean.overdueDate
+ val asOfString = if (TextUtils.isEmpty(overdueDate)) {
+ ""
+ } else {
+ String.format(getString(R.string.txt_card_list_end), overdueDate)
+ }
+ itemCardAsOf.text = asOfString
+ if (null == rechargeDeviceBean.pet) {
+ itemCardPetHead.appHeadImage.visibility = View.GONE
+ itemCardPetName.visibility = View.GONE
+ } else {
+ itemCardPetHead.appHeadImage.let {
+ it.visibility = View.VISIBLE
+ ViewUtil.instance.imageLoadUrl(it, rechargeDeviceBean.pet!!.imgurl)
+ }
+ itemCardPetName.let {
+ it.visibility = View.VISIBLE
+ it.text = rechargeDeviceBean.pet!!.petName
+ }
+ }
+ }
+
+ mViewBinding.rechargeDeviceDetailCnDescribe.let {
+ if (TextUtils.isEmpty(rechargeDeviceBean.period)) {
+ rechargeDeviceBean.period = "0"
+ }
+ val subscriptionPlanString =
+ String.format(getString(R.string.txt_surplus_day_how),
+ rechargeDeviceBean.surplusDays)
+ it.tvDescriptionSurplusDayContent.text = subscriptionPlanString
+ it.tvDescriptionExpiryDateContent.text = rechargeDeviceBean.overdueDate
+ }
+ break
+ }
+ }
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mViewBinding.btnRechargeDeviceDetailCnRecharge -> {
+ if (null != mRechargeDeviceBean) {
+ val intent = Intent(mContext, RechargeAmountCNActivity::class.java)
+ intent.putExtra(ConstantString.RechargeDevice, mRechargeDeviceBean)
+ startActivity(intent)
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeHistoryCNActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeHistoryCNActivity.kt
new file mode 100644
index 0000000..bae8cdf
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeHistoryCNActivity.kt
@@ -0,0 +1,53 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile.recharge.cn
+
+import androidx.activity.viewModels
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.abbidot.tracker.R
+import com.abbidot.tracker.deprecated.adapter.RechargeHistoryCNAdapter
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.databinding.ActivityRechargeHistoryCnBinding
+import com.abbidot.tracker.deprecated.ui.activity.vm.RechargeHistoryViewModel
+
+/**
+ * 国内充值记录
+ */
+class RechargeHistoryCNActivity :
+ BaseActivity(ActivityRechargeHistoryCnBinding::inflate) {
+
+ private val mRechargeHistoryViewModel: RechargeHistoryViewModel by viewModels()
+
+ private lateinit var mRechargeHistoryCNAdapter: RechargeHistoryCNAdapter
+
+ override fun getTopBar() = mViewBinding.rechargeDeviceDetailCnBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTopBarTitle(R.string.txt_card_history)
+
+ val deviceId = intent.extras?.getString(ConstantString.DeviceId, "").toString()
+
+ mRechargeHistoryCNAdapter = RechargeHistoryCNAdapter(mContext!!, null)
+
+ mViewBinding.rechargeHistoryCnRecyclerView.apply {
+ layoutManager = LinearLayoutManager(mContext)
+ addItemDecoration(DividerItemDecoration(mContext, DividerItemDecoration.VERTICAL))
+ adapter = mRechargeHistoryCNAdapter
+ }
+
+ mRechargeHistoryViewModel.getRechargeHistory(this, deviceId)
+ }
+
+ override fun liveDataObserve() {
+ mRechargeHistoryViewModel.mRechargeHistoryListLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val list = it.getOrNull()!!
+ mRechargeHistoryCNAdapter.setData(list, true)
+ }
+ })
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeOrderDetailCNActivity.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeOrderDetailCNActivity.kt
new file mode 100644
index 0000000..f923e5e
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/profile/recharge/cn/RechargeOrderDetailCNActivity.kt
@@ -0,0 +1,257 @@
+package com.abbidot.tracker.deprecated.ui.activity.profile.recharge.cn
+
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.Message
+import android.text.TextUtils
+import android.view.View
+import androidx.activity.viewModels
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.lifecycleScope
+import com.abbidot.baselibrary.constant.EventName
+import com.abbidot.baselibrary.eventbus.XEventBus
+import com.abbidot.baselibrary.util.LogUtil
+import com.abbidot.baselibrary.util.Utils
+import com.abbidot.tracker.R
+import com.abbidot.tracker.alipay.PayResult
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.RechargeDeviceBean
+import com.abbidot.tracker.bean.SetMealBean
+import com.abbidot.tracker.constant.ConstantInt
+import com.abbidot.tracker.constant.ConstantString
+import com.abbidot.tracker.constant.GetResultCallback
+import com.abbidot.tracker.databinding.ActivityRechargeOrderDetailCnBinding
+import com.abbidot.tracker.deprecated.ui.activity.vm.PayCNViewModel
+import com.abbidot.tracker.util.ThirdPartyUtil
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.alipay.sdk.app.PayTask
+import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet
+import com.tencent.mm.opensdk.modelpay.PayReq
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+
+/**
+ * 国内充值订单详情
+ */
+class RechargeOrderDetailCNActivity : BaseActivity(
+ ActivityRechargeOrderDetailCnBinding::inflate
+) {
+
+ private val mPayCNViewModel: PayCNViewModel by viewModels()
+
+ //设备
+ private var mRechargeDeviceBean: RechargeDeviceBean? = null
+
+ //套餐
+ private var mSetMealBean: SetMealBean? = null
+ private var mQMUIBottomSheet: QMUIBottomSheet? = null
+
+ private val alipaySDKPayFlag = 1
+
+ //支付方式
+ private var mPayWay = 0
+
+ //支付宝支付子线程
+ private lateinit var mHandlerThread: HandlerThread
+ private lateinit var mHandler: Handler
+
+ override fun getTopBar() = mViewBinding.rechargeOrderDetailCnBar.titleTopBar
+
+ override fun initData() {
+ super.initData()
+ setTopBarTitle(R.string.txt_pay_order_title)
+
+ mRechargeDeviceBean = Util.getParcelableAdaptive(
+ intent,
+ ConstantString.RechargeDevice,
+ RechargeDeviceBean::class.java
+ )
+ mSetMealBean =
+ Util.getParcelableAdaptive(intent, ConstantString.SetMeal, SetMealBean::class.java)
+
+ mViewBinding.apply {
+ ViewUtil.instance.setShapeRadius(rechargeOrderDetailCnDevice.root, 6)
+ ViewUtil.instance.setShapeRadius(rechargeOrderDetailCnAmount.root, 6)
+ rechargeOrderDetailCnPayWay.let {
+ it.text = getString(R.string.txt_select_payment_method)
+ it.detailTextView.visibility = View.VISIBLE
+ it.detailTextView.background =
+ ContextCompat.getDrawable(mContext!!, R.drawable.pic_wechatpay)
+
+ setOnClickListenerViews(startPayMoneyBtnCn, it)
+ }
+ }
+
+ //底部弹出菜单
+ val languageList = mutableListOf(R.drawable.pic_wechatpay, R.drawable.pic_alipay)
+ val bottomListSheetBuilder =
+ ViewUtil.instance.showBottomSheetList(mContext!!, { dialog, _, position, _ ->
+ dialog.dismiss()
+ mPayWay = position
+ mViewBinding.rechargeOrderDetailCnPayWay.detailTextView.background =
+ ContextCompat.getDrawable(mContext, languageList[position])
+ })
+ for (i in 0 until languageList.size) {
+ bottomListSheetBuilder.addItem(languageList[i], "", "")
+ }
+ mQMUIBottomSheet = bottomListSheetBuilder.build()
+
+ setRechargeDeviceData()
+ setSetMeal()
+
+ initAlipayThread()
+ }
+
+ /**
+ * 初始化支付宝支付线程
+ */
+ private fun initAlipayThread() {
+ mHandlerThread = HandlerThread("mHandlerThread")
+ mHandlerThread.start()
+ //支付宝支付结果回调
+ mHandler = Handler(mHandlerThread.looper) {
+ when (it.what) {
+ alipaySDKPayFlag -> {
+ @Suppress("UNCHECKED_CAST") val payResult =
+ PayResult(it.obj as Map)
+ //同步返回需要验证的信息
+ LogUtil.e("支付宝支付结果回调", payResult.toString())
+ mPayCNViewModel.alipayResultCallback(
+ this, payResult.resultStatus, mSetMealBean!!.accountFee
+ )
+ }
+ }
+ true
+ }
+ }
+
+ override fun liveDataObserve() {
+ mPayCNViewModel.mGetWxPayOrderLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()
+ data?.apply {
+ val request = PayReq()
+ request.appId = appid
+ request.partnerId = partnerid
+ request.prepayId = prepayid
+ request.packageValue = packageStr
+ request.nonceStr = noncestr
+ request.timeStamp = timestamp
+ request.sign = sign
+ ThirdPartyUtil.mApi.sendReq(request)
+ }
+ }
+ })
+ }
+
+ mPayCNViewModel.mGetAlipayOrderLiveData.observe(this) {
+ dealRequestResult(it, object : GetResultCallback {
+ override fun onResult(any: Any) {
+ val data = it.getOrNull()
+ data?.let {
+ //支付宝支付必须异步调用
+ lifecycleScope.launch(Dispatchers.IO) {
+ val alipay = PayTask(mActivity)
+ //订单信息
+ val result = alipay.payV2(data.orderString, true)
+ val msg = Message()
+ msg.what = alipaySDKPayFlag
+ msg.obj = result
+ mHandler.sendMessage(msg)
+ }
+ }
+ }
+ })
+ }
+
+ //支付成功返回
+ XEventBus.observe(this, EventName.PayBack) {
+ finish()
+ }
+ }
+
+ private fun setRechargeDeviceData() {
+ mRechargeDeviceBean?.apply {
+ mViewBinding.rechargeOrderDetailCnDevice.let {
+ it.itemCardDeviceName.text = this.deviceOutId
+ it.itemCardDayNumber.text = this.surplusDays.toString()
+ val overdueDate = this.overdueDate
+ val asOfString = if (TextUtils.isEmpty(overdueDate)) {
+ ""
+ } else {
+ String.format(getString(R.string.txt_card_list_end), overdueDate)
+ }
+ it.itemCardAsOf.text = asOfString
+
+ this.pet?.apply {
+ it.itemCardPetHead.appHeadImage.visibility = View.VISIBLE
+ it.itemCardPetName.visibility = View.VISIBLE
+ it.itemCardPetName.text = pet!!.petName
+ ViewUtil.instance.imageLoadUrl(it.itemCardPetHead.appHeadImage, pet!!.imgurl)
+ }
+ }
+ }
+ }
+
+ private fun setSetMeal() {
+ mSetMealBean?.apply {
+ val str = getString(R.string.txt_month_until) + "\t$accountFee"
+ mViewBinding.tvNeedPayMoneyCn.text = str
+ mViewBinding.rechargeOrderDetailCnAmount.let {
+ if (hotType == ConstantInt.Type1) {
+ it.rechargeAmountNormalHotImage.visibility = View.VISIBLE
+ } else {
+ it.rechargeAmountNormalHotImage.visibility = View.GONE
+ }
+ it.rechargeAmountTwoMoney.text = accountFee.toString()
+
+ it.txtRechargeAmountName.text = name
+
+ val perMonth = if (period > 1) {
+ String.format(getString(R.string.pet_managet_age), period)
+ } else {
+ String.format(getString(R.string.pet_managet_age_1), period)
+ }
+ it.rechargeAmountTwoTime.text = perMonth
+
+// val subscriptionPlan =
+// String.format(getString(R.string.txt_pay_amount_detail1), subscriptionFee)
+ it.txtSubscriptionPlanContent.text = "数量:x1"
+
+ val averageMonth = Utils.formatDecimal(accountFee / (12 * period), 2)
+ val monthString = String.format(getString(R.string.txt_perMonth), averageMonth)
+ it.rechargeAmountTwoDescription.text = monthString
+ }
+ }
+ }
+
+ /**
+ * 去支付
+ */
+ private fun goPay() {
+ when (mPayWay) {
+ 0 -> mPayCNViewModel.getWxPayOrder(this, mSetMealBean!!, mRechargeDeviceBean!!.deviceId)
+
+ 1 -> mPayCNViewModel.getAlipayOrder(
+ this, mSetMealBean!!, mRechargeDeviceBean!!.deviceId
+ )
+
+ }
+ }
+
+ override fun onClick(v: View?) {
+ when (v!!) {
+ mViewBinding.startPayMoneyBtnCn -> goPay()
+ mViewBinding.rechargeOrderDetailCnPayWay -> mQMUIBottomSheet?.show()
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ //线程退出释放
+ mHandlerThread.quit()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AddPetLabelsViewModel.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AddPetLabelsViewModel.kt
new file mode 100644
index 0000000..88666a5
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AddPetLabelsViewModel.kt
@@ -0,0 +1,64 @@
+package com.abbidot.tracker.deprecated.ui.activity.vm
+
+import android.text.TextUtils
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import androidx.recyclerview.widget.DiffUtil
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.base.BaseDiffCallBack
+import com.abbidot.tracker.bean.LabelBean
+import com.abbidot.tracker.retrofit2.NetworkApi
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ *Created by .yzq on 2022/3/3/003.
+ * @link
+ * @description:
+ */
+class AddPetLabelsViewModel : ViewModel() {
+
+ val mPetLabelsLiveData = MutableLiveData>>()
+ val mLabelListLiveData = MutableLiveData>()
+
+ fun getPetLabels(activity: BaseActivity<*>) {
+ activity.showLoading(true)
+ viewModelScope.launch {
+ val result = NetworkApi.getPetLabels()
+ mPetLabelsLiveData.value = result
+ }
+ }
+
+ /**
+ * 多个标签,隔开的字符串转数组
+ */
+ fun getLabelData(label: String) {
+ if (TextUtils.isEmpty(label)) return
+ val labels = label.split(",")
+ if (labels.isNotEmpty()) {
+ val labelList = mutableListOf()
+ labels.forEach { str ->
+ val labelBean = LabelBean(str)
+ labelList.add(labelBean)
+ }
+ mLabelListLiveData.value = labelList
+ }
+ }
+
+ fun setLabelData(adapter: BaseRecyclerAdapter, newList: MutableList) {
+ val oldList = adapter.getData()
+ if (oldList.size == 0) {
+ adapter.setData(newList, true)
+ return
+ }
+ viewModelScope.launch {
+ withContext(Dispatchers.Default) {
+ adapter.setData(newList)
+ DiffUtil.calculateDiff(BaseDiffCallBack(oldList, newList), true)
+ }.dispatchUpdatesTo(adapter)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AddTrackerDeviceViewModel.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AddTrackerDeviceViewModel.kt
new file mode 100644
index 0000000..47bbffc
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AddTrackerDeviceViewModel.kt
@@ -0,0 +1,84 @@
+package com.abbidot.tracker.deprecated.ui.activity.vm
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.util.MMKVUtil
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.OrderBean
+import com.abbidot.tracker.bean.RechargeDeviceBean
+import com.abbidot.tracker.retrofit2.NetworkApi
+import kotlinx.coroutines.launch
+
+/**
+ *Created by .yzq on 2022/4/9/009.
+ * @link
+ * @description:添加绑定设备
+ */
+class AddTrackerDeviceViewModel : ViewModel() {
+
+ val mGetMacLiveData = MutableLiveData>()
+ val mGetIccIdLiveData = MutableLiveData>()
+ val mActiveDeviceLiveData = MutableLiveData>()
+ val mUpdatePayDeviceStateLiveData = MutableLiveData>()
+ val mDeviceOrderStatusLiveData = MutableLiveData>()
+
+ /**
+ * 获取设备mac地址
+ */
+ fun getMacId(activity: BaseActivity<*>, deviceOutId: String) {
+ activity.showLoading(true)
+ val userId = MMKVUtil.getString(MMKVKey.UserId)
+ viewModelScope.launch {
+ val result = NetworkApi.getMacId(userId, deviceOutId)
+ mGetMacLiveData.value = result
+ }
+ }
+
+ /**
+ * 获取设备iccid
+ */
+ fun getIccId(activity: BaseActivity<*>, deviceOutId: String) {
+ activity.showLoading(true)
+ viewModelScope.launch {
+ val result = NetworkApi.getIccId(deviceOutId)
+ mGetIccIdLiveData.value = result
+ }
+ }
+
+ /**
+ * 上电激活设备,更新状态
+ *@param addStatus 设备添加状态,1 为上电激活成功
+ */
+ fun activeDevice(activity: BaseActivity<*>, deviceId: String, addStatus: Int) {
+ activity.showLoading(true)
+ viewModelScope.launch {
+ val result = NetworkApi.updateStatus(deviceId, addStatus)
+ mActiveDeviceLiveData.value = result
+ }
+ }
+
+ /**
+ * 支付成功后,更新绑定状态
+ */
+ fun updatePayDeviceState(activity: BaseActivity<*>, deviceId: String) {
+ activity.showLoading(true)
+ viewModelScope.launch {
+ val userId = MMKVUtil.getString(MMKVKey.UserId)
+ val result = NetworkApi.updatePayDeviceState(deviceId, userId)
+ mUpdatePayDeviceStateLiveData.value = result
+ }
+ }
+
+ /**
+ * 获取设备订单状态
+ */
+ fun getDeviceOrderStatus(activity: BaseActivity<*>, deviceOutId: String) {
+ activity.showLoading(true)
+ viewModelScope.launch {
+ val result = NetworkApi.getDeviceOrderStatus(deviceOutId)
+ mDeviceOrderStatusLiveData.value = result
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AutomaticSubscribeViewModel.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AutomaticSubscribeViewModel.kt
new file mode 100644
index 0000000..922e7d3
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/AutomaticSubscribeViewModel.kt
@@ -0,0 +1,43 @@
+package com.abbidot.tracker.deprecated.ui.activity.vm
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.util.MMKVUtil
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.PayResultBean
+import com.abbidot.tracker.bean.RechargeDeviceBean
+import com.abbidot.tracker.bean.SetMealBean
+import com.abbidot.tracker.retrofit2.NetworkApi
+import kotlinx.coroutines.launch
+
+/**
+ *Created by .yzq on 2022/3/26/026.
+ * @link
+ * @description:开通/关闭自动订阅,自动续费
+ */
+class AutomaticSubscribeViewModel : ViewModel() {
+ val mCancelSubscribeLiveData = MutableLiveData>()
+ fun cancelSubscriptions(activity: BaseActivity<*>, rechargeDeviceBean: RechargeDeviceBean) {
+ activity.showLoading(true)
+ viewModelScope.launch {
+ val result = NetworkApi.cancelSubscriptions(rechargeDeviceBean.orderId,
+ rechargeDeviceBean.payType, rechargeDeviceBean.subscriptionsId)
+ mCancelSubscribeLiveData.value = result
+ }
+ }
+
+ val mSubscribeLiveData = MutableLiveData>()
+ fun subscription(activity: BaseActivity<*>, setMealBean: SetMealBean, deviceId: String) {
+ activity.showLoading(true)
+ viewModelScope.launch {
+ val userId = MMKVUtil.getString(MMKVKey.UserId )
+ val username = MMKVUtil.getString(MMKVKey.UserName)
+ val result = NetworkApi.subscription(setMealBean.name, deviceId,
+ setMealBean.accountFee.toString(), setMealBean.subscriptionFee.toString(),
+ setMealBean.period.toString(), userId, username)
+ mSubscribeLiveData.value = result
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/BraintreePalViewModel.kt b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/BraintreePalViewModel.kt
new file mode 100644
index 0000000..36701e3
--- /dev/null
+++ b/app/src/main/java/com/abbidot/tracker/deprecated/ui/activity/vm/BraintreePalViewModel.kt
@@ -0,0 +1,250 @@
+package com.abbidot.tracker.deprecated.ui.activity.vm
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import androidx.recyclerview.widget.DiffUtil
+import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.list.BaseRecyclerAdapter
+import com.abbidot.baselibrary.util.LogUtil
+import com.abbidot.baselibrary.util.MMKVUtil
+import com.abbidot.tracker.R
+import com.abbidot.tracker.base.BaseActivity
+import com.abbidot.tracker.bean.*
+import com.abbidot.tracker.database.MyDatabase
+import com.abbidot.tracker.diff.PaymentMethodDiffCallBack
+import com.abbidot.tracker.retrofit2.NetworkApi
+import com.abbidot.tracker.util.Util
+import com.abbidot.tracker.util.ViewUtil
+import com.braintreepayments.api.*
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ *Created by .yzq on 2022/3/28/028.
+ * @link
+ * @description:braintree支付
+ */
+class BraintreePalViewModel : ViewModel() {
+
+ //是否是沙盒环境
+ private val isSandbox = true
+
+ /**
+ * 标记化密钥 初始化sdk
+ */
+ //沙盒测试
+ private val sandboxTokenizationKey = "sandbox_csgnn5ww_dp75dg57ptvqwz9b"
+
+ //生产正式
+ private val productionTokenizationKey = "sandbox_csgnn5ww_dp75dg57ptvqwz9b"
+
+ val mBraintreeClientTokenLiveData = MutableLiveData